diff options
Diffstat (limited to 'libpod')
53 files changed, 3278 insertions, 10098 deletions
diff --git a/libpod/adapter/client.go b/libpod/adapter/client.go new file mode 100644 index 000000000..b3bb9acae --- /dev/null +++ b/libpod/adapter/client.go @@ -0,0 +1,36 @@ +// +build remoteclient + +package adapter + +import ( + "os" + + "github.com/sirupsen/logrus" + "github.com/varlink/go/varlink" +) + +// DefaultAddress is the default address of the varlink socket +const DefaultAddress = "unix:/run/podman/io.podman" + +// Connect provides a varlink connection +func (r RemoteRuntime) Connect() (*varlink.Connection, error) { + var err error + var connection *varlink.Connection + if bridge := os.Getenv("PODMAN_VARLINK_BRIDGE"); bridge != "" { + logrus.Infof("Connecting with varlink bridge") + logrus.Debugf("%s", bridge) + connection, err = varlink.NewBridge(bridge) + } else { + address := os.Getenv("PODMAN_VARLINK_ADDRESS") + if address == "" { + address = DefaultAddress + } + logrus.Infof("Connecting with varlink address") + logrus.Debugf("%s", address) + connection, err = varlink.NewConnection(address) + } + if err != nil { + return nil, err + } + return connection, nil +} diff --git a/libpod/adapter/containers_remote.go b/libpod/adapter/containers_remote.go new file mode 100644 index 000000000..9623304e5 --- /dev/null +++ b/libpod/adapter/containers_remote.go @@ -0,0 +1,50 @@ +// +build remoteclient + +package adapter + +import ( + "encoding/json" + + iopodman "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/libpod" + "github.com/containers/libpod/pkg/inspect" +) + +// Inspect returns an inspect struct from varlink +func (c *Container) Inspect(size bool) (*inspect.ContainerInspectData, error) { + reply, err := iopodman.ContainerInspectData().Call(c.Runtime.Conn, c.ID()) + if err != nil { + return nil, err + } + data := inspect.ContainerInspectData{} + if err := json.Unmarshal([]byte(reply), &data); err != nil { + return nil, err + } + return &data, err +} + +// ID returns the ID of the container +func (c *Container) ID() string { + return c.config.ID +} + +// GetArtifact returns a container's artifacts +func (c *Container) GetArtifact(name string) ([]byte, error) { + var data []byte + reply, err := iopodman.ContainerArtifacts().Call(c.Runtime.Conn, c.ID(), name) + if err != nil { + return nil, err + } + if err := json.Unmarshal([]byte(reply), &data); err != nil { + return nil, err + } + return data, err +} + +// Config returns a container's Config ... same as ctr.Config() +func (c *Container) Config() *libpod.ContainerConfig { + if c.config != nil { + return c.config + } + return c.Runtime.Config(c.ID()) +} diff --git a/libpod/adapter/images_remote.go b/libpod/adapter/images_remote.go new file mode 100644 index 000000000..e7b38dccc --- /dev/null +++ b/libpod/adapter/images_remote.go @@ -0,0 +1,24 @@ +// +build remoteclient + +package adapter + +import ( + "context" + "encoding/json" + + iopodman "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/pkg/inspect" +) + +// Inspect returns returns an ImageData struct from over a varlink connection +func (i *ContainerImage) Inspect(ctx context.Context) (*inspect.ImageData, error) { + reply, err := iopodman.InspectImage().Call(i.Runtime.Conn, i.ID()) + if err != nil { + return nil, err + } + data := inspect.ImageData{} + if err := json.Unmarshal([]byte(reply), &data); err != nil { + return nil, err + } + return &data, nil +} diff --git a/libpod/adapter/info_remote.go b/libpod/adapter/info_remote.go new file mode 100644 index 000000000..3b691ed17 --- /dev/null +++ b/libpod/adapter/info_remote.go @@ -0,0 +1,56 @@ +// +build remoteclient + +package adapter + +import ( + "encoding/json" + + "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/libpod" +) + +// Info returns information for the host system and its components +func (r RemoteRuntime) Info() ([]libpod.InfoData, error) { + // TODO the varlink implementation for info should be updated to match the output for regular info + var ( + reply []libpod.InfoData + hostInfo map[string]interface{} + store map[string]interface{} + ) + + registries := make(map[string]interface{}) + insecureRegistries := make(map[string]interface{}) + conn, err := r.Connect() + if err != nil { + return nil, err + } + defer conn.Close() + info, err := iopodman.GetInfo().Call(conn) + if err != nil { + return nil, err + } + + // info.host -> map[string]interface{} + h, err := json.Marshal(info.Host) + if err != nil { + return nil, err + } + json.Unmarshal(h, &hostInfo) + + // info.store -> map[string]interface{} + s, err := json.Marshal(info.Store) + if err != nil { + return nil, err + } + json.Unmarshal(s, &store) + + registries["registries"] = info.Registries + insecureRegistries["registries"] = info.Insecure_registries + + // Add everything to the reply + reply = append(reply, libpod.InfoData{Type: "host", Data: hostInfo}) + reply = append(reply, libpod.InfoData{Type: "registries", Data: registries}) + reply = append(reply, libpod.InfoData{Type: "insecure registries", Data: insecureRegistries}) + reply = append(reply, libpod.InfoData{Type: "store", Data: store}) + return reply, nil +} diff --git a/libpod/adapter/runtime.go b/libpod/adapter/runtime.go new file mode 100644 index 000000000..1f3599082 --- /dev/null +++ b/libpod/adapter/runtime.go @@ -0,0 +1,101 @@ +// +build !remoteclient + +package adapter + +import ( + "context" + "io" + + "github.com/containers/image/types" + "github.com/containers/libpod/cmd/podman/libpodruntime" + "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/image" + "github.com/urfave/cli" +) + +// LocalRuntime describes a typical libpod runtime +type LocalRuntime struct { + *libpod.Runtime + Remote bool +} + +// ContainerImage ... +type ContainerImage struct { + *image.Image +} + +// Container ... +type Container struct { + *libpod.Container +} + +// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it +func GetRuntime(c *cli.Context) (*LocalRuntime, error) { + runtime, err := libpodruntime.GetRuntime(c) + if err != nil { + return nil, err + } + return &LocalRuntime{ + Runtime: runtime, + }, nil +} + +// GetImages returns a slice of images in containerimages +func (r *LocalRuntime) GetImages() ([]*ContainerImage, error) { + var containerImages []*ContainerImage + images, err := r.Runtime.ImageRuntime().GetImages() + if err != nil { + return nil, err + } + for _, i := range images { + containerImages = append(containerImages, &ContainerImage{i}) + } + return containerImages, nil + +} + +// NewImageFromLocal returns a containerimage representation of a image from local storage +func (r *LocalRuntime) NewImageFromLocal(name string) (*ContainerImage, error) { + img, err := r.Runtime.ImageRuntime().NewFromLocal(name) + if err != nil { + return nil, err + } + return &ContainerImage{img}, nil +} + +// LoadFromArchiveReference calls into local storage to load an image from an archive +func (r *LocalRuntime) LoadFromArchiveReference(ctx context.Context, srcRef types.ImageReference, signaturePolicyPath string, writer io.Writer) ([]*ContainerImage, error) { + var containerImages []*ContainerImage + imgs, err := r.Runtime.ImageRuntime().LoadFromArchiveReference(ctx, srcRef, signaturePolicyPath, writer) + if err != nil { + return nil, err + } + for _, i := range imgs { + ci := ContainerImage{i} + containerImages = append(containerImages, &ci) + } + return containerImages, nil +} + +// New calls into local storage to look for an image in local storage or to pull it +func (r *LocalRuntime) New(ctx context.Context, name, signaturePolicyPath, authfile string, writer io.Writer, dockeroptions *image.DockerRegistryOptions, signingoptions image.SigningOptions, forcePull bool) (*ContainerImage, error) { + img, err := r.Runtime.ImageRuntime().New(ctx, name, signaturePolicyPath, authfile, writer, dockeroptions, signingoptions, forcePull) + if err != nil { + return nil, err + } + return &ContainerImage{img}, nil +} + +// RemoveImage calls into local storage and removes an image +func (r *LocalRuntime) RemoveImage(ctx context.Context, img *ContainerImage, force bool) (string, error) { + return r.Runtime.RemoveImage(ctx, img.Image, force) +} + +// LookupContainer ... +func (r *LocalRuntime) LookupContainer(idOrName string) (*Container, error) { + ctr, err := r.Runtime.LookupContainer(idOrName) + if err != nil { + return nil, err + } + return &Container{ctr}, nil +} diff --git a/libpod/adapter/runtime_remote.go b/libpod/adapter/runtime_remote.go new file mode 100644 index 000000000..7189348bc --- /dev/null +++ b/libpod/adapter/runtime_remote.go @@ -0,0 +1,322 @@ +// +build remoteclient + +package adapter + +import ( + "context" + "encoding/json" + "fmt" + "io" + "strings" + "time" + + "github.com/containers/image/types" + "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/image" + "github.com/opencontainers/go-digest" + "github.com/sirupsen/logrus" + "github.com/urfave/cli" + "github.com/varlink/go/varlink" +) + +// ImageRuntime is wrapper for image runtime +type RemoteImageRuntime struct{} + +// RemoteRuntime describes a wrapper runtime struct +type RemoteRuntime struct { + Conn *varlink.Connection + Remote bool +} + +// LocalRuntime describes a typical libpod runtime +type LocalRuntime struct { + *RemoteRuntime +} + +// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it +func GetRuntime(c *cli.Context) (*LocalRuntime, error) { + runtime := RemoteRuntime{} + conn, err := runtime.Connect() + if err != nil { + return nil, err + } + rr := RemoteRuntime{ + Conn: conn, + Remote: true, + } + foo := LocalRuntime{ + &rr, + } + return &foo, nil +} + +// Shutdown is a bogus wrapper for compat with the libpod runtime +func (r RemoteRuntime) Shutdown(force bool) error { + return nil +} + +// ContainerImage +type ContainerImage struct { + remoteImage +} + +type remoteImage struct { + ID string + Labels map[string]string + RepoTags []string + RepoDigests []string + Parent string + Size int64 + Created time.Time + InputName string + Names []string + Digest digest.Digest + isParent bool + Runtime *LocalRuntime +} + +// Container ... +type Container struct { + remoteContainer +} + +// remoteContainer .... +type remoteContainer struct { + Runtime *LocalRuntime + config *libpod.ContainerConfig + state *libpod.ContainerState +} + +// GetImages returns a slice of containerimages over a varlink connection +func (r *LocalRuntime) GetImages() ([]*ContainerImage, error) { + var newImages []*ContainerImage + images, err := iopodman.ListImages().Call(r.Conn) + if err != nil { + return nil, err + } + for _, i := range images { + name := i.Id + if len(i.RepoTags) > 1 { + name = i.RepoTags[0] + } + newImage, err := imageInListToContainerImage(i, name, r) + if err != nil { + return nil, err + } + newImages = append(newImages, newImage) + } + return newImages, nil +} + +func imageInListToContainerImage(i iopodman.ImageInList, name string, runtime *LocalRuntime) (*ContainerImage, error) { + created, err := splitStringDate(i.Created) + if err != nil { + return nil, err + } + ri := remoteImage{ + InputName: name, + ID: i.Id, + Labels: i.Labels, + RepoTags: i.RepoTags, + RepoDigests: i.RepoTags, + Parent: i.ParentId, + Size: i.Size, + Created: created, + Names: i.RepoTags, + isParent: i.IsParent, + Runtime: runtime, + } + return &ContainerImage{ri}, nil +} + +// NewImageFromLocal returns a container image representation of a image over varlink +func (r *LocalRuntime) NewImageFromLocal(name string) (*ContainerImage, error) { + img, err := iopodman.GetImage().Call(r.Conn, name) + if err != nil { + return nil, err + } + return imageInListToContainerImage(img, name, r) + +} + +// LoadFromArchiveReference creates an image from a local archive +func (r *LocalRuntime) LoadFromArchiveReference(ctx context.Context, srcRef types.ImageReference, signaturePolicyPath string, writer io.Writer) ([]*ContainerImage, error) { + // TODO We need to find a way to leak certDir, creds, and the tlsverify into this function, normally this would + // come from cli options but we don't want want those in here either. + imageID, err := iopodman.PullImage().Call(r.Conn, srcRef.DockerReference().String(), "", "", signaturePolicyPath, true) + if err != nil { + return nil, err + } + newImage, err := r.NewImageFromLocal(imageID) + if err != nil { + return nil, err + } + return []*ContainerImage{newImage}, nil +} + +// New calls into local storage to look for an image in local storage or to pull it +func (r *LocalRuntime) New(ctx context.Context, name, signaturePolicyPath, authfile string, writer io.Writer, dockeroptions *image.DockerRegistryOptions, signingoptions image.SigningOptions, forcePull bool) (*ContainerImage, error) { + // TODO Creds needs to be figured out here too, like above + tlsBool := dockeroptions.DockerInsecureSkipTLSVerify + // Remember SkipTlsVerify is the opposite of tlsverify + // If tlsBook is true or undefined, we do not skip + SkipTlsVerify := false + if tlsBool == types.OptionalBoolFalse { + SkipTlsVerify = true + } + imageID, err := iopodman.PullImage().Call(r.Conn, name, dockeroptions.DockerCertPath, "", signaturePolicyPath, SkipTlsVerify) + if err != nil { + return nil, err + } + newImage, err := r.NewImageFromLocal(imageID) + if err != nil { + return nil, err + } + return newImage, nil +} + +func splitStringDate(d string) (time.Time, error) { + fields := strings.Fields(d) + t := fmt.Sprintf("%sT%sZ", fields[0], fields[1]) + return time.ParseInLocation(time.RFC3339Nano, t, time.UTC) +} + +// IsParent goes through the layers in the store and checks if i.TopLayer is +// the parent of any other layer in store. Double check that image with that +// layer exists as well. +func (ci *ContainerImage) IsParent() (bool, error) { + return ci.remoteImage.isParent, nil +} + +// ID returns the image ID as a string +func (ci *ContainerImage) ID() string { + return ci.remoteImage.ID +} + +// Names returns a string array of names associated with the image +func (ci *ContainerImage) Names() []string { + return ci.remoteImage.Names +} + +// Created returns the time the image was created +func (ci *ContainerImage) Created() time.Time { + return ci.remoteImage.Created +} + +// Size returns the size of the image +func (ci *ContainerImage) Size(ctx context.Context) (*uint64, error) { + usize := uint64(ci.remoteImage.Size) + return &usize, nil +} + +// Digest returns the image's digest +func (ci *ContainerImage) Digest() digest.Digest { + return ci.remoteImage.Digest +} + +// Labels returns a map of the image's labels +func (ci *ContainerImage) Labels(ctx context.Context) (map[string]string, error) { + return ci.remoteImage.Labels, nil +} + +// Dangling returns a bool if the image is "dangling" +func (ci *ContainerImage) Dangling() bool { + return len(ci.Names()) == 0 +} + +// TagImage ... +func (ci *ContainerImage) TagImage(tag string) error { + _, err := iopodman.TagImage().Call(ci.Runtime.Conn, ci.ID(), tag) + return err +} + +// RemoveImage calls varlink to remove an image +func (r *LocalRuntime) RemoveImage(ctx context.Context, img *ContainerImage, force bool) (string, error) { + return iopodman.RemoveImage().Call(r.Conn, img.InputName, force) +} + +// History returns the history of an image and its layers +func (ci *ContainerImage) History(ctx context.Context) ([]*image.History, error) { + var imageHistories []*image.History + + reply, err := iopodman.HistoryImage().Call(ci.Runtime.Conn, ci.InputName) + if err != nil { + return nil, err + } + for _, h := range reply { + created, err := splitStringDate(h.Created) + if err != nil { + return nil, err + } + ih := image.History{ + ID: h.Id, + Created: &created, + CreatedBy: h.CreatedBy, + Size: h.Size, + Comment: h.Comment, + } + imageHistories = append(imageHistories, &ih) + } + return imageHistories, nil +} + +// LookupContainer gets basic information about container over a varlink +// connection and then translates it to a *Container +func (r *LocalRuntime) LookupContainer(idOrName string) (*Container, error) { + state, err := r.ContainerState(idOrName) + if err != nil { + return nil, err + } + config := r.Config(idOrName) + if err != nil { + return nil, err + } + + rc := remoteContainer{ + r, + config, + state, + } + + c := Container{ + rc, + } + return &c, nil +} + +func (r *LocalRuntime) GetLatestContainer() (*Container, error) { + return nil, libpod.ErrNotImplemented +} + +// ContainerState returns the "state" of the container. +func (r *LocalRuntime) ContainerState(name string) (*libpod.ContainerState, error) { //no-lint + reply, err := iopodman.ContainerStateData().Call(r.Conn, name) + if err != nil { + return nil, err + } + data := libpod.ContainerState{} + if err := json.Unmarshal([]byte(reply), &data); err != nil { + return nil, err + } + return &data, err + +} + +// Config returns a container config +func (r *LocalRuntime) Config(name string) *libpod.ContainerConfig { + // TODO the Spec being returned is not populated. Matt and I could not figure out why. Will defer + // further looking into it for after devconf. + // The libpod function for this has no errors so we are kind of in a tough + // spot here. Logging the errors for now. + reply, err := iopodman.ContainerConfig().Call(r.Conn, name) + if err != nil { + logrus.Error("call to container.config failed") + } + data := libpod.ContainerConfig{} + if err := json.Unmarshal([]byte(reply), &data); err != nil { + logrus.Error("failed to unmarshal container inspect data") + } + return &data + +} diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index ba8f7375a..5bc15dd7f 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -2,15 +2,17 @@ package libpod import ( "bytes" - "encoding/json" "strings" "sync" "github.com/boltdb/bolt" + jsoniter "github.com/json-iterator/go" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) +var json = jsoniter.ConfigCompatibleWithStandardLibrary + // BoltState is a state implementation backed by a Bolt DB type BoltState struct { valid bool @@ -203,7 +205,7 @@ func (s *BoltState) Refresh() error { return errors.Wrapf(ErrInternal, "container %s missing state in DB", string(id)) } - state := new(containerState) + state := new(ContainerState) if err := json.Unmarshal(stateBytes, state); err != nil { return errors.Wrapf(err, "error unmarshalling state for container %s", string(id)) @@ -322,8 +324,8 @@ func (s *BoltState) Container(id string) (*Container, error) { ctrID := []byte(id) ctr := new(Container) - ctr.config = new(Config) - ctr.state = new(containerState) + ctr.config = new(ContainerConfig) + ctr.state = new(ContainerState) db, err := s.getDBCon() if err != nil { @@ -358,8 +360,8 @@ func (s *BoltState) LookupContainer(idOrName string) (*Container, error) { } ctr := new(Container) - ctr.config = new(Config) - ctr.state = new(containerState) + ctr.config = new(ContainerConfig) + ctr.state = new(ContainerState) db, err := s.getDBCon() if err != nil { @@ -540,7 +542,7 @@ func (s *BoltState) UpdateContainer(ctr *Container) error { return errors.Wrapf(ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) } - newState := new(containerState) + newState := new(ContainerState) netNSPath := "" ctrID := []byte(ctr.ID()) @@ -751,8 +753,8 @@ func (s *BoltState) AllContainers() ([]*Container, error) { } ctr := new(Container) - ctr.config = new(Config) - ctr.state = new(containerState) + ctr.config = new(ContainerConfig) + ctr.state = new(ContainerState) if err := s.getContainerFromDB(id, ctr, ctrBucket); err != nil { // If the error is a namespace mismatch, we can @@ -1137,8 +1139,8 @@ func (s *BoltState) PodContainers(pod *Pod) ([]*Container, error) { // Iterate through all containers in the pod err = podCtrs.ForEach(func(id, val []byte) error { newCtr := new(Container) - newCtr.config = new(Config) - newCtr.state = new(containerState) + newCtr.config = new(ContainerConfig) + newCtr.state = new(ContainerState) ctrs = append(ctrs, newCtr) return s.getContainerFromDB(id, newCtr, ctrBkt) diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go index 06f8dcb24..ea150cfac 100644 --- a/libpod/boltdb_state_internal.go +++ b/libpod/boltdb_state_internal.go @@ -2,8 +2,6 @@ package libpod import ( "bytes" - "encoding/json" - "path/filepath" "runtime" "strings" @@ -288,10 +286,9 @@ func (s *BoltState) getContainerFromDB(id []byte, ctr *Container, ctrsBkt *bolt. } // Get the lock - lockPath := filepath.Join(s.runtime.lockDir, string(id)) - lock, err := storage.GetLockfile(lockPath) + lock, err := s.runtime.lockManager.RetrieveLock(ctr.config.LockID) if err != nil { - return errors.Wrapf(err, "error retrieving lockfile for container %s", string(id)) + return errors.Wrapf(err, "error retrieving lock for container %s", string(id)) } ctr.lock = lock @@ -324,10 +321,9 @@ func (s *BoltState) getPodFromDB(id []byte, pod *Pod, podBkt *bolt.Bucket) error } // Get the lock - lockPath := filepath.Join(s.runtime.lockDir, string(id)) - lock, err := storage.GetLockfile(lockPath) + lock, err := s.runtime.lockManager.RetrieveLock(pod.config.LockID) if err != nil { - return errors.Wrapf(err, "error retrieving lockfile for pod %s", string(id)) + return errors.Wrapf(err, "error retrieving lock for pod %s", string(id)) } pod.lock = lock @@ -353,8 +349,7 @@ func (s *BoltState) getVolumeFromDB(name []byte, volume *Volume, volBkt *bolt.Bu } // Get the lock - lockPath := filepath.Join(s.runtime.lockDir, string(name)) - lock, err := storage.GetLockfile(lockPath) + lock, err := s.runtime.lockManager.RetrieveLock(volume.config.LockID) if err != nil { return errors.Wrapf(err, "error retrieving lockfile for volume %s", string(name)) } diff --git a/libpod/boltdb_state_linux.go b/libpod/boltdb_state_linux.go index d91f311e5..09a9be606 100644 --- a/libpod/boltdb_state_linux.go +++ b/libpod/boltdb_state_linux.go @@ -8,7 +8,7 @@ import ( // replaceNetNS handle network namespace transitions after updating a // container's state. -func replaceNetNS(netNSPath string, ctr *Container, newState *containerState) error { +func replaceNetNS(netNSPath string, ctr *Container, newState *ContainerState) error { if netNSPath != "" { // Check if the container's old state has a good netns if ctr.state.NetNS != nil && netNSPath == ctr.state.NetNS.Path() { diff --git a/libpod/boltdb_state_unsupported.go b/libpod/boltdb_state_unsupported.go index 64610d304..244dc51a0 100644 --- a/libpod/boltdb_state_unsupported.go +++ b/libpod/boltdb_state_unsupported.go @@ -3,7 +3,7 @@ package libpod // replaceNetNS is exclusive to the Linux platform and is a no-op elsewhere -func replaceNetNS(netNSPath string, ctr *Container, newState *containerState) error { +func replaceNetNS(netNSPath string, ctr *Container, newState *ContainerState) error { return nil } diff --git a/libpod/common_test.go b/libpod/common_test.go index 6c7434fd2..df730098e 100644 --- a/libpod/common_test.go +++ b/libpod/common_test.go @@ -1,24 +1,22 @@ package libpod import ( - "encoding/json" "net" - "path/filepath" "reflect" "strings" "testing" "time" - "github.com/containers/storage" + "github.com/containers/libpod/libpod/lock" "github.com/cri-o/ocicni/pkg/ocicni" "github.com/opencontainers/runtime-tools/generate" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -func getTestContainer(id, name, locksDir string) (*Container, error) { +func getTestContainer(id, name string, manager lock.Manager) (*Container, error) { ctr := &Container{ - config: &Config{ + config: &ContainerConfig{ ID: id, Name: name, RootfsImageID: id, @@ -50,7 +48,7 @@ func getTestContainer(id, name, locksDir string) (*Container, error) { }, }, }, - state: &containerState{ + state: &ContainerState{ State: ContainerStateRunning, ConfigPath: "/does/not/exist/specs/" + id, RunDir: "/does/not/exist/tmp/", @@ -90,18 +88,18 @@ func getTestContainer(id, name, locksDir string) (*Container, error) { ctr.config.Labels["test"] = "testing" - // Must make lockfile or container will error on being retrieved from DB - lockPath := filepath.Join(locksDir, id) - lock, err := storage.GetLockfile(lockPath) + // Allocate a lock for the container + lock, err := manager.AllocateLock() if err != nil { return nil, err } ctr.lock = lock + ctr.config.LockID = lock.ID() return ctr, nil } -func getTestPod(id, name, locksDir string) (*Pod, error) { +func getTestPod(id, name string, manager lock.Manager) (*Pod, error) { pod := &Pod{ config: &PodConfig{ ID: id, @@ -115,38 +113,39 @@ func getTestPod(id, name, locksDir string) (*Pod, error) { valid: true, } - lockPath := filepath.Join(locksDir, id) - lock, err := storage.GetLockfile(lockPath) + // Allocate a lock for the pod + lock, err := manager.AllocateLock() if err != nil { return nil, err } pod.lock = lock + pod.config.LockID = lock.ID() return pod, nil } -func getTestCtrN(n, lockPath string) (*Container, error) { - return getTestContainer(strings.Repeat(n, 32), "test"+n, lockPath) +func getTestCtrN(n string, manager lock.Manager) (*Container, error) { + return getTestContainer(strings.Repeat(n, 32), "test"+n, manager) } -func getTestCtr1(lockPath string) (*Container, error) { - return getTestCtrN("1", lockPath) +func getTestCtr1(manager lock.Manager) (*Container, error) { + return getTestCtrN("1", manager) } -func getTestCtr2(lockPath string) (*Container, error) { - return getTestCtrN("2", lockPath) +func getTestCtr2(manager lock.Manager) (*Container, error) { + return getTestCtrN("2", manager) } -func getTestPodN(n, lockPath string) (*Pod, error) { - return getTestPod(strings.Repeat(n, 32), "test"+n, lockPath) +func getTestPodN(n string, manager lock.Manager) (*Pod, error) { + return getTestPod(strings.Repeat(n, 32), "test"+n, manager) } -func getTestPod1(lockPath string) (*Pod, error) { - return getTestPodN("1", lockPath) +func getTestPod1(manager lock.Manager) (*Pod, error) { + return getTestPodN("1", manager) } -func getTestPod2(lockPath string) (*Pod, error) { - return getTestPodN("2", lockPath) +func getTestPod2(manager lock.Manager) (*Pod, error) { + return getTestPodN("2", manager) } // This horrible hack tests if containers are equal in a way that should handle @@ -165,15 +164,17 @@ func testContainersEqual(t *testing.T, a, b *Container, allowedEmpty bool) { require.NotNil(t, a.state) require.NotNil(t, b.state) - aConfig := new(Config) - bConfig := new(Config) - aState := new(containerState) - bState := new(containerState) + aConfig := new(ContainerConfig) + bConfig := new(ContainerConfig) + aState := new(ContainerState) + bState := new(ContainerState) - blankState := new(containerState) + blankState := new(ContainerState) assert.Equal(t, a.valid, b.valid) + assert.Equal(t, a.lock.ID(), b.lock.ID()) + aConfigJSON, err := json.Marshal(a.config) assert.NoError(t, err) err = json.Unmarshal(aConfigJSON, aConfig) @@ -223,6 +224,8 @@ func testPodsEqual(t *testing.T, a, b *Pod, allowedEmpty bool) { assert.Equal(t, a.valid, b.valid) + assert.Equal(t, a.lock.ID(), b.lock.ID()) + assert.EqualValues(t, a.config, b.config) if allowedEmpty { diff --git a/libpod/container.go b/libpod/container.go index b4190344a..b0589be3b 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -2,6 +2,7 @@ package libpod import ( "fmt" + "io/ioutil" "net" "os" "path/filepath" @@ -9,6 +10,7 @@ import ( "github.com/containernetworking/cni/pkg/types" cnitypes "github.com/containernetworking/cni/pkg/types/current" + "github.com/containers/libpod/libpod/lock" "github.com/containers/libpod/pkg/namespaces" "github.com/containers/storage" "github.com/cri-o/ocicni/pkg/ocicni" @@ -112,9 +114,9 @@ func (ns LinuxNS) String() string { // syncContainer() immediately after locking. // ffjson: skip type Container struct { - config *Config + config *ContainerConfig - state *containerState + state *ContainerState // Batched indicates that a container has been locked as part of a // Batch() operation @@ -122,17 +124,22 @@ type Container struct { batched bool valid bool - lock storage.Locker + lock lock.Locker runtime *Runtime rootlessSlirpSyncR *os.File rootlessSlirpSyncW *os.File + + // A restored container should have the same IP address as before + // being checkpointed. If requestedIP is set it will be used instead + // of config.StaticIP. + requestedIP net.IP } -// containerState contains the current state of the container +// ContainerState contains the current state of the container // It is stored on disk in a tmpfs and recreated on reboot // easyjson:json -type containerState struct { +type ContainerState struct { // The current state of the running container State ContainerStatus `json:"state"` // The path to the JSON OCI runtime spec for this container @@ -199,11 +206,11 @@ type ExecSession struct { PID int `json:"pid"` } -// Config contains all information that was used to create the +// ContainerConfig contains all information that was used to create the // container. It may not be changed once created. // It is stored, read-only, on disk // easyjson:json -type Config struct { +type ContainerConfig struct { Spec *spec.Spec `json:"spec"` ID string `json:"id"` Name string `json:"name"` @@ -211,6 +218,8 @@ type Config struct { Pod string `json:"pod,omitempty"` // Namespace the container is in Namespace string `json:"namespace,omitempty"` + // ID of this container's lock + LockID uint32 `json:"lockID"` // TODO consider breaking these subsections up into smaller structs @@ -341,6 +350,9 @@ type Config struct { PostConfigureNetNS bool `json:"postConfigureNetNS"` + // OCIRuntime used to create the container + OCIRuntime string `json:"runtime,omitempty"` + // ExitCommand is the container's exit command. // This Command will be executed when the container exits ExitCommand []string `json:"exitCommand,omitempty"` @@ -382,8 +394,8 @@ func (t ContainerStatus) String() string { // Unlocked // Config returns the configuration used to create the container -func (c *Container) Config() *Config { - returnConfig := new(Config) +func (c *Container) Config() *ContainerConfig { + returnConfig := new(ContainerConfig) deepcopier.Copy(c.config).To(returnConfig) return returnConfig @@ -399,6 +411,31 @@ func (c *Container) Spec() *spec.Spec { return returnSpec } +// specFromState returns the unmarshalled json config of the container. If the +// config does not exist (e.g., because the container was never started) return +// the spec from the config. +func (c *Container) specFromState() (*spec.Spec, error) { + returnSpec := c.config.Spec + + if f, err := os.Open(c.state.ConfigPath); err == nil { + returnSpec = new(spec.Spec) + content, err := ioutil.ReadAll(f) + if err != nil { + return nil, errors.Wrapf(err, "error reading container config") + } + if err := json.Unmarshal([]byte(content), &returnSpec); err != nil { + return nil, errors.Wrapf(err, "error unmarshalling container config") + } + } else { + // ignore when the file does not exist + if !os.IsNotExist(err) { + return nil, errors.Wrapf(err, "error opening container config") + } + } + + return returnSpec, nil +} + // ID returns the container's ID func (c *Container) ID() string { return c.config.ID @@ -1026,3 +1063,18 @@ func networkDisabled(c *Container) (bool, error) { } return false, nil } + +// ContainerState returns containerstate struct +func (c *Container) ContainerState() (*ContainerState, error) { + if !c.batched { + c.lock.Lock() + defer c.lock.Unlock() + + if err := c.syncContainer(); err != nil { + return nil, err + } + } + returnConfig := new(ContainerState) + deepcopier.Copy(c.state).To(returnConfig) + return c.state, nil +} diff --git a/libpod/container_api.go b/libpod/container_api.go index 09bc46905..149867759 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -3,6 +3,7 @@ package libpod import ( "context" "fmt" + "io" "io/ioutil" "os" "strconv" @@ -262,7 +263,7 @@ func (c *Container) Kill(signal uint) error { // Exec starts a new process inside the container // TODO allow specifying streams to attach to // TODO investigate allowing exec without attaching -func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) error { +func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir string) error { var capList []string locked := false @@ -324,7 +325,7 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) e logrus.Debugf("Creating new exec session in container %s with session id %s", c.ID(), sessionID) - execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, hostUser, sessionID) + execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, hostUser, sessionID) if err != nil { return errors.Wrapf(err, "error exec %s", c.ID()) } @@ -413,6 +414,25 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) e return waitErr } +// AttachStreams contains streams that will be attached to the container +type AttachStreams struct { + // OutputStream will be attached to container's STDOUT + OutputStream io.WriteCloser + // ErrorStream will be attached to container's STDERR + ErrorStream io.WriteCloser + // InputStream will be attached to container's STDIN + InputStream io.Reader + // AttachOutput is whether to attach to STDOUT + // If false, stdout will not be attached + AttachOutput bool + // AttachError is whether to attach to STDERR + // If false, stdout will not be attached + AttachError bool + // AttachInput is whether to attach to STDIN + // If false, stdout will not be attached + AttachInput bool +} + // Attach attaches to a container func (c *Container) Attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize) error { if !c.batched { diff --git a/libpod/container_attach.go b/libpod/container_attach_linux.go index f925c3897..1d6f0bd96 100644 --- a/libpod/container_attach.go +++ b/libpod/container_attach_linux.go @@ -1,3 +1,5 @@ +//+build linux + package libpod import ( @@ -27,25 +29,6 @@ const ( AttachPipeStderr = 3 ) -// AttachStreams contains streams that will be attached to the container -type AttachStreams struct { - // OutputStream will be attached to container's STDOUT - OutputStream io.WriteCloser - // ErrorStream will be attached to container's STDERR - ErrorStream io.WriteCloser - // InputStream will be attached to container's STDIN - InputStream io.Reader - // AttachOutput is whether to attach to STDOUT - // If false, stdout will not be attached - AttachOutput bool - // AttachError is whether to attach to STDERR - // If false, stdout will not be attached - AttachError bool - // AttachInput is whether to attach to STDIN - // If false, stdout will not be attached - AttachInput bool -} - // Attach to the given container // Does not check if state is appropriate func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool) error { diff --git a/libpod/container_attach_unsupported.go b/libpod/container_attach_unsupported.go new file mode 100644 index 000000000..068652b29 --- /dev/null +++ b/libpod/container_attach_unsupported.go @@ -0,0 +1,11 @@ +//+build !linux + +package libpod + +import ( + "k8s.io/client-go/tools/remotecommand" +) + +func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool) error { + return ErrNotImplemented +} diff --git a/libpod/container_easyjson.go b/libpod/container_easyjson.go deleted file mode 100644 index 299a645e1..000000000 --- a/libpod/container_easyjson.go +++ /dev/null @@ -1,8191 +0,0 @@ -// +build seccomp ostree selinux varlink exclude_graphdriver_devicemapper - -// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. - -package libpod - -import ( - json "encoding/json" - types "github.com/containernetworking/cni/pkg/types" - current "github.com/containernetworking/cni/pkg/types/current" - namespaces "github.com/containers/libpod/pkg/namespaces" - storage "github.com/containers/storage" - idtools "github.com/containers/storage/pkg/idtools" - ocicni "github.com/cri-o/ocicni/pkg/ocicni" - easyjson "github.com/mailru/easyjson" - jlexer "github.com/mailru/easyjson/jlexer" - jwriter "github.com/mailru/easyjson/jwriter" - specs_go "github.com/opencontainers/runtime-spec/specs-go" - net "net" - os "os" -) - -// suppress unused package warning -var ( - _ *json.RawMessage - _ *jlexer.Lexer - _ *jwriter.Writer - _ easyjson.Marshaler -) - -func easyjson1dbef17bDecodeGithubComContainersLibpodLibpod(in *jlexer.Lexer, out *containerState) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "state": - out.State = ContainerStatus(in.Int()) - case "configPath": - out.ConfigPath = string(in.String()) - case "runDir": - out.RunDir = string(in.String()) - case "destinationRunDir": - out.DestinationRunDir = string(in.String()) - case "mounted": - out.Mounted = bool(in.Bool()) - case "mountPoint": - out.Mountpoint = string(in.String()) - case "realMountPoint": - out.RealMountpoint = string(in.String()) - case "startedTime": - if data := in.Raw(); in.Ok() { - in.AddError((out.StartedTime).UnmarshalJSON(data)) - } - case "finishedTime": - if data := in.Raw(); in.Ok() { - in.AddError((out.FinishedTime).UnmarshalJSON(data)) - } - case "exitCode": - out.ExitCode = int32(in.Int32()) - case "exited": - out.Exited = bool(in.Bool()) - case "oomKilled": - out.OOMKilled = bool(in.Bool()) - case "pid": - out.PID = int(in.Int()) - case "execSessions": - if in.IsNull() { - in.Skip() - } else { - in.Delim('{') - if !in.IsDelim('}') { - out.ExecSessions = make(map[string]*ExecSession) - } else { - out.ExecSessions = nil - } - for !in.IsDelim('}') { - key := string(in.String()) - in.WantColon() - var v1 *ExecSession - if in.IsNull() { - in.Skip() - v1 = nil - } else { - if v1 == nil { - v1 = new(ExecSession) - } - if data := in.Raw(); in.Ok() { - in.AddError((*v1).UnmarshalJSON(data)) - } - } - (out.ExecSessions)[key] = v1 - in.WantComma() - } - in.Delim('}') - } - case "networkResults": - if in.IsNull() { - in.Skip() - out.NetworkStatus = nil - } else { - in.Delim('[') - if out.NetworkStatus == nil { - if !in.IsDelim(']') { - out.NetworkStatus = make([]*current.Result, 0, 8) - } else { - out.NetworkStatus = []*current.Result{} - } - } else { - out.NetworkStatus = (out.NetworkStatus)[:0] - } - for !in.IsDelim(']') { - var v2 *current.Result - if in.IsNull() { - in.Skip() - v2 = nil - } else { - if v2 == nil { - v2 = new(current.Result) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComContainernetworkingCniPkgTypesCurrent(in, &*v2) - } - out.NetworkStatus = append(out.NetworkStatus, v2) - in.WantComma() - } - in.Delim(']') - } - case "bindMounts": - if in.IsNull() { - in.Skip() - } else { - in.Delim('{') - if !in.IsDelim('}') { - out.BindMounts = make(map[string]string) - } else { - out.BindMounts = nil - } - for !in.IsDelim('}') { - key := string(in.String()) - in.WantColon() - var v3 string - v3 = string(in.String()) - (out.BindMounts)[key] = v3 - in.WantComma() - } - in.Delim('}') - } - case "userNSRoot": - out.UserNSRoot = string(in.String()) - case "extensionStageHooks": - if in.IsNull() { - in.Skip() - } else { - in.Delim('{') - if !in.IsDelim('}') { - out.ExtensionStageHooks = make(map[string][]specs_go.Hook) - } else { - out.ExtensionStageHooks = nil - } - for !in.IsDelim('}') { - key := string(in.String()) - in.WantColon() - var v4 []specs_go.Hook - if in.IsNull() { - in.Skip() - v4 = nil - } else { - in.Delim('[') - if v4 == nil { - if !in.IsDelim(']') { - v4 = make([]specs_go.Hook, 0, 1) - } else { - v4 = []specs_go.Hook{} - } - } else { - v4 = (v4)[:0] - } - for !in.IsDelim(']') { - var v5 specs_go.Hook - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo(in, &v5) - v4 = append(v4, v5) - in.WantComma() - } - in.Delim(']') - } - (out.ExtensionStageHooks)[key] = v4 - in.WantComma() - } - in.Delim('}') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodLibpod(out *jwriter.Writer, in containerState) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"state\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int(int(in.State)) - } - if in.ConfigPath != "" { - const prefix string = ",\"configPath\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.ConfigPath)) - } - if in.RunDir != "" { - const prefix string = ",\"runDir\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.RunDir)) - } - if in.DestinationRunDir != "" { - const prefix string = ",\"destinationRunDir\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.DestinationRunDir)) - } - if in.Mounted { - const prefix string = ",\"mounted\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.Mounted)) - } - if in.Mountpoint != "" { - const prefix string = ",\"mountPoint\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Mountpoint)) - } - if in.RealMountpoint != "" { - const prefix string = ",\"realMountPoint\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.RealMountpoint)) - } - if true { - const prefix string = ",\"startedTime\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Raw((in.StartedTime).MarshalJSON()) - } - if true { - const prefix string = ",\"finishedTime\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Raw((in.FinishedTime).MarshalJSON()) - } - if in.ExitCode != 0 { - const prefix string = ",\"exitCode\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int32(int32(in.ExitCode)) - } - if in.Exited { - const prefix string = ",\"exited\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.Exited)) - } - if in.OOMKilled { - const prefix string = ",\"oomKilled\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.OOMKilled)) - } - if in.PID != 0 { - const prefix string = ",\"pid\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int(int(in.PID)) - } - if len(in.ExecSessions) != 0 { - const prefix string = ",\"execSessions\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('{') - v6First := true - for v6Name, v6Value := range in.ExecSessions { - if v6First { - v6First = false - } else { - out.RawByte(',') - } - out.String(string(v6Name)) - out.RawByte(':') - if v6Value == nil { - out.RawString("null") - } else { - out.Raw((*v6Value).MarshalJSON()) - } - } - out.RawByte('}') - } - } - if len(in.NetworkStatus) != 0 { - const prefix string = ",\"networkResults\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v7, v8 := range in.NetworkStatus { - if v7 > 0 { - out.RawByte(',') - } - if v8 == nil { - out.RawString("null") - } else { - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComContainernetworkingCniPkgTypesCurrent(out, *v8) - } - } - out.RawByte(']') - } - } - if len(in.BindMounts) != 0 { - const prefix string = ",\"bindMounts\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('{') - v9First := true - for v9Name, v9Value := range in.BindMounts { - if v9First { - v9First = false - } else { - out.RawByte(',') - } - out.String(string(v9Name)) - out.RawByte(':') - out.String(string(v9Value)) - } - out.RawByte('}') - } - } - if in.UserNSRoot != "" { - const prefix string = ",\"userNSRoot\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.UserNSRoot)) - } - if len(in.ExtensionStageHooks) != 0 { - const prefix string = ",\"extensionStageHooks\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('{') - v10First := true - for v10Name, v10Value := range in.ExtensionStageHooks { - if v10First { - v10First = false - } else { - out.RawByte(',') - } - out.String(string(v10Name)) - out.RawByte(':') - if v10Value == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { - out.RawString("null") - } else { - out.RawByte('[') - for v11, v12 := range v10Value { - if v11 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo(out, v12) - } - out.RawByte(']') - } - } - out.RawByte('}') - } - } - out.RawByte('}') -} - -// MarshalJSON supports json.Marshaler interface -func (v containerState) MarshalJSON() ([]byte, error) { - w := jwriter.Writer{} - easyjson1dbef17bEncodeGithubComContainersLibpodLibpod(&w, v) - return w.Buffer.BuildBytes(), w.Error -} - -// MarshalEasyJSON supports easyjson.Marshaler interface -func (v containerState) MarshalEasyJSON(w *jwriter.Writer) { - easyjson1dbef17bEncodeGithubComContainersLibpodLibpod(w, v) -} - -// UnmarshalJSON supports json.Unmarshaler interface -func (v *containerState) UnmarshalJSON(data []byte) error { - r := jlexer.Lexer{Data: data} - easyjson1dbef17bDecodeGithubComContainersLibpodLibpod(&r, v) - return r.Error() -} - -// UnmarshalEasyJSON supports easyjson.Unmarshaler interface -func (v *containerState) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson1dbef17bDecodeGithubComContainersLibpodLibpod(l, v) -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo(in *jlexer.Lexer, out *specs_go.Hook) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "path": - out.Path = string(in.String()) - case "args": - if in.IsNull() { - in.Skip() - out.Args = nil - } else { - in.Delim('[') - if out.Args == nil { - if !in.IsDelim(']') { - out.Args = make([]string, 0, 4) - } else { - out.Args = []string{} - } - } else { - out.Args = (out.Args)[:0] - } - for !in.IsDelim(']') { - var v13 string - v13 = string(in.String()) - out.Args = append(out.Args, v13) - in.WantComma() - } - in.Delim(']') - } - case "env": - if in.IsNull() { - in.Skip() - out.Env = nil - } else { - in.Delim('[') - if out.Env == nil { - if !in.IsDelim(']') { - out.Env = make([]string, 0, 4) - } else { - out.Env = []string{} - } - } else { - out.Env = (out.Env)[:0] - } - for !in.IsDelim(']') { - var v14 string - v14 = string(in.String()) - out.Env = append(out.Env, v14) - in.WantComma() - } - in.Delim(']') - } - case "timeout": - if in.IsNull() { - in.Skip() - out.Timeout = nil - } else { - if out.Timeout == nil { - out.Timeout = new(int) - } - *out.Timeout = int(in.Int()) - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo(out *jwriter.Writer, in specs_go.Hook) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"path\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Path)) - } - if len(in.Args) != 0 { - const prefix string = ",\"args\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v15, v16 := range in.Args { - if v15 > 0 { - out.RawByte(',') - } - out.String(string(v16)) - } - out.RawByte(']') - } - } - if len(in.Env) != 0 { - const prefix string = ",\"env\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v17, v18 := range in.Env { - if v17 > 0 { - out.RawByte(',') - } - out.String(string(v18)) - } - out.RawByte(']') - } - } - if in.Timeout != nil { - const prefix string = ",\"timeout\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int(int(*in.Timeout)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComContainernetworkingCniPkgTypesCurrent(in *jlexer.Lexer, out *current.Result) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "cniVersion": - out.CNIVersion = string(in.String()) - case "interfaces": - if in.IsNull() { - in.Skip() - out.Interfaces = nil - } else { - in.Delim('[') - if out.Interfaces == nil { - if !in.IsDelim(']') { - out.Interfaces = make([]*current.Interface, 0, 8) - } else { - out.Interfaces = []*current.Interface{} - } - } else { - out.Interfaces = (out.Interfaces)[:0] - } - for !in.IsDelim(']') { - var v19 *current.Interface - if in.IsNull() { - in.Skip() - v19 = nil - } else { - if v19 == nil { - v19 = new(current.Interface) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComContainernetworkingCniPkgTypesCurrent1(in, &*v19) - } - out.Interfaces = append(out.Interfaces, v19) - in.WantComma() - } - in.Delim(']') - } - case "ips": - if in.IsNull() { - in.Skip() - out.IPs = nil - } else { - in.Delim('[') - if out.IPs == nil { - if !in.IsDelim(']') { - out.IPs = make([]*current.IPConfig, 0, 8) - } else { - out.IPs = []*current.IPConfig{} - } - } else { - out.IPs = (out.IPs)[:0] - } - for !in.IsDelim(']') { - var v20 *current.IPConfig - if in.IsNull() { - in.Skip() - v20 = nil - } else { - if v20 == nil { - v20 = new(current.IPConfig) - } - if data := in.Raw(); in.Ok() { - in.AddError((*v20).UnmarshalJSON(data)) - } - } - out.IPs = append(out.IPs, v20) - in.WantComma() - } - in.Delim(']') - } - case "routes": - if in.IsNull() { - in.Skip() - out.Routes = nil - } else { - in.Delim('[') - if out.Routes == nil { - if !in.IsDelim(']') { - out.Routes = make([]*types.Route, 0, 8) - } else { - out.Routes = []*types.Route{} - } - } else { - out.Routes = (out.Routes)[:0] - } - for !in.IsDelim(']') { - var v21 *types.Route - if in.IsNull() { - in.Skip() - v21 = nil - } else { - if v21 == nil { - v21 = new(types.Route) - } - if data := in.Raw(); in.Ok() { - in.AddError((*v21).UnmarshalJSON(data)) - } - } - out.Routes = append(out.Routes, v21) - in.WantComma() - } - in.Delim(']') - } - case "dns": - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComContainernetworkingCniPkgTypes(in, &out.DNS) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComContainernetworkingCniPkgTypesCurrent(out *jwriter.Writer, in current.Result) { - out.RawByte('{') - first := true - _ = first - if in.CNIVersion != "" { - const prefix string = ",\"cniVersion\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.CNIVersion)) - } - if len(in.Interfaces) != 0 { - const prefix string = ",\"interfaces\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v22, v23 := range in.Interfaces { - if v22 > 0 { - out.RawByte(',') - } - if v23 == nil { - out.RawString("null") - } else { - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComContainernetworkingCniPkgTypesCurrent1(out, *v23) - } - } - out.RawByte(']') - } - } - if len(in.IPs) != 0 { - const prefix string = ",\"ips\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v24, v25 := range in.IPs { - if v24 > 0 { - out.RawByte(',') - } - if v25 == nil { - out.RawString("null") - } else { - out.Raw((*v25).MarshalJSON()) - } - } - out.RawByte(']') - } - } - if len(in.Routes) != 0 { - const prefix string = ",\"routes\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v26, v27 := range in.Routes { - if v26 > 0 { - out.RawByte(',') - } - if v27 == nil { - out.RawString("null") - } else { - out.Raw((*v27).MarshalJSON()) - } - } - out.RawByte(']') - } - } - if true { - const prefix string = ",\"dns\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComContainernetworkingCniPkgTypes(out, in.DNS) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComContainernetworkingCniPkgTypes(in *jlexer.Lexer, out *types.DNS) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "nameservers": - if in.IsNull() { - in.Skip() - out.Nameservers = nil - } else { - in.Delim('[') - if out.Nameservers == nil { - if !in.IsDelim(']') { - out.Nameservers = make([]string, 0, 4) - } else { - out.Nameservers = []string{} - } - } else { - out.Nameservers = (out.Nameservers)[:0] - } - for !in.IsDelim(']') { - var v28 string - v28 = string(in.String()) - out.Nameservers = append(out.Nameservers, v28) - in.WantComma() - } - in.Delim(']') - } - case "domain": - out.Domain = string(in.String()) - case "search": - if in.IsNull() { - in.Skip() - out.Search = nil - } else { - in.Delim('[') - if out.Search == nil { - if !in.IsDelim(']') { - out.Search = make([]string, 0, 4) - } else { - out.Search = []string{} - } - } else { - out.Search = (out.Search)[:0] - } - for !in.IsDelim(']') { - var v29 string - v29 = string(in.String()) - out.Search = append(out.Search, v29) - in.WantComma() - } - in.Delim(']') - } - case "options": - if in.IsNull() { - in.Skip() - out.Options = nil - } else { - in.Delim('[') - if out.Options == nil { - if !in.IsDelim(']') { - out.Options = make([]string, 0, 4) - } else { - out.Options = []string{} - } - } else { - out.Options = (out.Options)[:0] - } - for !in.IsDelim(']') { - var v30 string - v30 = string(in.String()) - out.Options = append(out.Options, v30) - in.WantComma() - } - in.Delim(']') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComContainernetworkingCniPkgTypes(out *jwriter.Writer, in types.DNS) { - out.RawByte('{') - first := true - _ = first - if len(in.Nameservers) != 0 { - const prefix string = ",\"nameservers\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v31, v32 := range in.Nameservers { - if v31 > 0 { - out.RawByte(',') - } - out.String(string(v32)) - } - out.RawByte(']') - } - } - if in.Domain != "" { - const prefix string = ",\"domain\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Domain)) - } - if len(in.Search) != 0 { - const prefix string = ",\"search\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v33, v34 := range in.Search { - if v33 > 0 { - out.RawByte(',') - } - out.String(string(v34)) - } - out.RawByte(']') - } - } - if len(in.Options) != 0 { - const prefix string = ",\"options\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v35, v36 := range in.Options { - if v35 > 0 { - out.RawByte(',') - } - out.String(string(v36)) - } - out.RawByte(']') - } - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComContainernetworkingCniPkgTypesCurrent1(in *jlexer.Lexer, out *current.Interface) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "name": - out.Name = string(in.String()) - case "mac": - out.Mac = string(in.String()) - case "sandbox": - out.Sandbox = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComContainernetworkingCniPkgTypesCurrent1(out *jwriter.Writer, in current.Interface) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"name\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Name)) - } - if in.Mac != "" { - const prefix string = ",\"mac\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Mac)) - } - if in.Sandbox != "" { - const prefix string = ",\"sandbox\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Sandbox)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodLibpod1(in *jlexer.Lexer, out *ExecSession) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "id": - out.ID = string(in.String()) - case "command": - if in.IsNull() { - in.Skip() - out.Command = nil - } else { - in.Delim('[') - if out.Command == nil { - if !in.IsDelim(']') { - out.Command = make([]string, 0, 4) - } else { - out.Command = []string{} - } - } else { - out.Command = (out.Command)[:0] - } - for !in.IsDelim(']') { - var v37 string - v37 = string(in.String()) - out.Command = append(out.Command, v37) - in.WantComma() - } - in.Delim(']') - } - case "pid": - out.PID = int(in.Int()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodLibpod1(out *jwriter.Writer, in ExecSession) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"id\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.ID)) - } - { - const prefix string = ",\"command\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.Command == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { - out.RawString("null") - } else { - out.RawByte('[') - for v38, v39 := range in.Command { - if v38 > 0 { - out.RawByte(',') - } - out.String(string(v39)) - } - out.RawByte(']') - } - } - { - const prefix string = ",\"pid\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int(int(in.PID)) - } - out.RawByte('}') -} - -// MarshalJSON supports json.Marshaler interface -func (v ExecSession) MarshalJSON() ([]byte, error) { - w := jwriter.Writer{} - easyjson1dbef17bEncodeGithubComContainersLibpodLibpod1(&w, v) - return w.Buffer.BuildBytes(), w.Error -} - -// MarshalEasyJSON supports easyjson.Marshaler interface -func (v ExecSession) MarshalEasyJSON(w *jwriter.Writer) { - easyjson1dbef17bEncodeGithubComContainersLibpodLibpod1(w, v) -} - -// UnmarshalJSON supports json.Unmarshaler interface -func (v *ExecSession) UnmarshalJSON(data []byte) error { - r := jlexer.Lexer{Data: data} - easyjson1dbef17bDecodeGithubComContainersLibpodLibpod1(&r, v) - return r.Error() -} - -// UnmarshalEasyJSON supports easyjson.Unmarshaler interface -func (v *ExecSession) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson1dbef17bDecodeGithubComContainersLibpodLibpod1(l, v) -} -func easyjson1dbef17bDecodeGithubComContainersLibpodLibpod2(in *jlexer.Lexer, out *Config) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "spec": - if in.IsNull() { - in.Skip() - out.Spec = nil - } else { - if out.Spec == nil { - out.Spec = new(specs_go.Spec) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo1(in, &*out.Spec) - } - case "id": - out.ID = string(in.String()) - case "name": - out.Name = string(in.String()) - case "pod": - out.Pod = string(in.String()) - case "namespace": - out.Namespace = string(in.String()) - case "idMappingsOptions": - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComContainersStorage(in, &out.IDMappings) - case "rootfsImageID": - out.RootfsImageID = string(in.String()) - case "rootfsImageName": - out.RootfsImageName = string(in.String()) - case "rootfs": - out.Rootfs = string(in.String()) - case "imageVolumes": - out.ImageVolumes = bool(in.Bool()) - case "ShmDir": - out.ShmDir = string(in.String()) - case "shmSize": - out.ShmSize = int64(in.Int64()) - case "staticDir": - out.StaticDir = string(in.String()) - case "mounts": - if in.IsNull() { - in.Skip() - out.Mounts = nil - } else { - in.Delim('[') - if out.Mounts == nil { - if !in.IsDelim(']') { - out.Mounts = make([]string, 0, 4) - } else { - out.Mounts = []string{} - } - } else { - out.Mounts = (out.Mounts)[:0] - } - for !in.IsDelim(']') { - var v40 string - v40 = string(in.String()) - out.Mounts = append(out.Mounts, v40) - in.WantComma() - } - in.Delim(']') - } - case "privileged": - out.Privileged = bool(in.Bool()) - case "ProcessLabel": - out.ProcessLabel = string(in.String()) - case "MountLabel": - out.MountLabel = string(in.String()) - case "labelopts": - if in.IsNull() { - in.Skip() - out.LabelOpts = nil - } else { - in.Delim('[') - if out.LabelOpts == nil { - if !in.IsDelim(']') { - out.LabelOpts = make([]string, 0, 4) - } else { - out.LabelOpts = []string{} - } - } else { - out.LabelOpts = (out.LabelOpts)[:0] - } - for !in.IsDelim(']') { - var v41 string - v41 = string(in.String()) - out.LabelOpts = append(out.LabelOpts, v41) - in.WantComma() - } - in.Delim(']') - } - case "user": - out.User = string(in.String()) - case "groups": - if in.IsNull() { - in.Skip() - out.Groups = nil - } else { - in.Delim('[') - if out.Groups == nil { - if !in.IsDelim(']') { - out.Groups = make([]string, 0, 4) - } else { - out.Groups = []string{} - } - } else { - out.Groups = (out.Groups)[:0] - } - for !in.IsDelim(']') { - var v42 string - v42 = string(in.String()) - out.Groups = append(out.Groups, v42) - in.WantComma() - } - in.Delim(']') - } - case "ipcNsCtr": - out.IPCNsCtr = string(in.String()) - case "mountNsCtr": - out.MountNsCtr = string(in.String()) - case "netNsCtr": - out.NetNsCtr = string(in.String()) - case "pidNsCtr": - out.PIDNsCtr = string(in.String()) - case "userNsCtr": - out.UserNsCtr = string(in.String()) - case "utsNsCtr": - out.UTSNsCtr = string(in.String()) - case "cgroupNsCtr": - out.CgroupNsCtr = string(in.String()) - case "Dependencies": - if in.IsNull() { - in.Skip() - out.Dependencies = nil - } else { - in.Delim('[') - if out.Dependencies == nil { - if !in.IsDelim(']') { - out.Dependencies = make([]string, 0, 4) - } else { - out.Dependencies = []string{} - } - } else { - out.Dependencies = (out.Dependencies)[:0] - } - for !in.IsDelim(']') { - var v43 string - v43 = string(in.String()) - out.Dependencies = append(out.Dependencies, v43) - in.WantComma() - } - in.Delim(']') - } - case "createNetNS": - out.CreateNetNS = bool(in.Bool()) - case "staticIP": - if data := in.UnsafeBytes(); in.Ok() { - in.AddError((out.StaticIP).UnmarshalText(data)) - } - case "portMappings": - if in.IsNull() { - in.Skip() - out.PortMappings = nil - } else { - in.Delim('[') - if out.PortMappings == nil { - if !in.IsDelim(']') { - out.PortMappings = make([]ocicni.PortMapping, 0, 1) - } else { - out.PortMappings = []ocicni.PortMapping{} - } - } else { - out.PortMappings = (out.PortMappings)[:0] - } - for !in.IsDelim(']') { - var v44 ocicni.PortMapping - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComCriOOcicniPkgOcicni(in, &v44) - out.PortMappings = append(out.PortMappings, v44) - in.WantComma() - } - in.Delim(']') - } - case "dnsServer": - if in.IsNull() { - in.Skip() - out.DNSServer = nil - } else { - in.Delim('[') - if out.DNSServer == nil { - if !in.IsDelim(']') { - out.DNSServer = make([]net.IP, 0, 2) - } else { - out.DNSServer = []net.IP{} - } - } else { - out.DNSServer = (out.DNSServer)[:0] - } - for !in.IsDelim(']') { - var v45 net.IP - if data := in.UnsafeBytes(); in.Ok() { - in.AddError((v45).UnmarshalText(data)) - } - out.DNSServer = append(out.DNSServer, v45) - in.WantComma() - } - in.Delim(']') - } - case "dnsSearch": - if in.IsNull() { - in.Skip() - out.DNSSearch = nil - } else { - in.Delim('[') - if out.DNSSearch == nil { - if !in.IsDelim(']') { - out.DNSSearch = make([]string, 0, 4) - } else { - out.DNSSearch = []string{} - } - } else { - out.DNSSearch = (out.DNSSearch)[:0] - } - for !in.IsDelim(']') { - var v46 string - v46 = string(in.String()) - out.DNSSearch = append(out.DNSSearch, v46) - in.WantComma() - } - in.Delim(']') - } - case "dnsOption": - if in.IsNull() { - in.Skip() - out.DNSOption = nil - } else { - in.Delim('[') - if out.DNSOption == nil { - if !in.IsDelim(']') { - out.DNSOption = make([]string, 0, 4) - } else { - out.DNSOption = []string{} - } - } else { - out.DNSOption = (out.DNSOption)[:0] - } - for !in.IsDelim(']') { - var v47 string - v47 = string(in.String()) - out.DNSOption = append(out.DNSOption, v47) - in.WantComma() - } - in.Delim(']') - } - case "hostsAdd": - if in.IsNull() { - in.Skip() - out.HostAdd = nil - } else { - in.Delim('[') - if out.HostAdd == nil { - if !in.IsDelim(']') { - out.HostAdd = make([]string, 0, 4) - } else { - out.HostAdd = []string{} - } - } else { - out.HostAdd = (out.HostAdd)[:0] - } - for !in.IsDelim(']') { - var v48 string - v48 = string(in.String()) - out.HostAdd = append(out.HostAdd, v48) - in.WantComma() - } - in.Delim(']') - } - case "networks": - if in.IsNull() { - in.Skip() - out.Networks = nil - } else { - in.Delim('[') - if out.Networks == nil { - if !in.IsDelim(']') { - out.Networks = make([]string, 0, 4) - } else { - out.Networks = []string{} - } - } else { - out.Networks = (out.Networks)[:0] - } - for !in.IsDelim(']') { - var v49 string - v49 = string(in.String()) - out.Networks = append(out.Networks, v49) - in.WantComma() - } - in.Delim(']') - } - case "networkMode": - out.NetMode = namespaces.NetworkMode(in.String()) - case "userVolumes": - if in.IsNull() { - in.Skip() - out.UserVolumes = nil - } else { - in.Delim('[') - if out.UserVolumes == nil { - if !in.IsDelim(']') { - out.UserVolumes = make([]string, 0, 4) - } else { - out.UserVolumes = []string{} - } - } else { - out.UserVolumes = (out.UserVolumes)[:0] - } - for !in.IsDelim(']') { - var v50 string - v50 = string(in.String()) - out.UserVolumes = append(out.UserVolumes, v50) - in.WantComma() - } - in.Delim(']') - } - case "entrypoint": - if in.IsNull() { - in.Skip() - out.Entrypoint = nil - } else { - in.Delim('[') - if out.Entrypoint == nil { - if !in.IsDelim(']') { - out.Entrypoint = make([]string, 0, 4) - } else { - out.Entrypoint = []string{} - } - } else { - out.Entrypoint = (out.Entrypoint)[:0] - } - for !in.IsDelim(']') { - var v51 string - v51 = string(in.String()) - out.Entrypoint = append(out.Entrypoint, v51) - in.WantComma() - } - in.Delim(']') - } - case "command": - if in.IsNull() { - in.Skip() - out.Command = nil - } else { - in.Delim('[') - if out.Command == nil { - if !in.IsDelim(']') { - out.Command = make([]string, 0, 4) - } else { - out.Command = []string{} - } - } else { - out.Command = (out.Command)[:0] - } - for !in.IsDelim(']') { - var v52 string - v52 = string(in.String()) - out.Command = append(out.Command, v52) - in.WantComma() - } - in.Delim(']') - } - case "stdin": - out.Stdin = bool(in.Bool()) - case "labels": - if in.IsNull() { - in.Skip() - } else { - in.Delim('{') - if !in.IsDelim('}') { - out.Labels = make(map[string]string) - } else { - out.Labels = nil - } - for !in.IsDelim('}') { - key := string(in.String()) - in.WantColon() - var v53 string - v53 = string(in.String()) - (out.Labels)[key] = v53 - in.WantComma() - } - in.Delim('}') - } - case "stopSignal": - out.StopSignal = uint(in.Uint()) - case "stopTimeout": - out.StopTimeout = uint(in.Uint()) - case "createdTime": - if data := in.Raw(); in.Ok() { - in.AddError((out.CreatedTime).UnmarshalJSON(data)) - } - case "cgroupParent": - out.CgroupParent = string(in.String()) - case "logPath": - out.LogPath = string(in.String()) - case "conmonPidFile": - out.ConmonPidFile = string(in.String()) - case "postConfigureNetNS": - out.PostConfigureNetNS = bool(in.Bool()) - case "exitCommand": - if in.IsNull() { - in.Skip() - out.ExitCommand = nil - } else { - in.Delim('[') - if out.ExitCommand == nil { - if !in.IsDelim(']') { - out.ExitCommand = make([]string, 0, 4) - } else { - out.ExitCommand = []string{} - } - } else { - out.ExitCommand = (out.ExitCommand)[:0] - } - for !in.IsDelim(']') { - var v54 string - v54 = string(in.String()) - out.ExitCommand = append(out.ExitCommand, v54) - in.WantComma() - } - in.Delim(']') - } - case "LocalVolumes": - if in.IsNull() { - in.Skip() - out.LocalVolumes = nil - } else { - in.Delim('[') - if out.LocalVolumes == nil { - if !in.IsDelim(']') { - out.LocalVolumes = make([]string, 0, 4) - } else { - out.LocalVolumes = []string{} - } - } else { - out.LocalVolumes = (out.LocalVolumes)[:0] - } - for !in.IsDelim(']') { - var v55 string - v55 = string(in.String()) - out.LocalVolumes = append(out.LocalVolumes, v55) - in.WantComma() - } - in.Delim(']') - } - case "pause": - out.IsInfra = bool(in.Bool()) - case "systemd": - out.Systemd = bool(in.Bool()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodLibpod2(out *jwriter.Writer, in Config) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"spec\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.Spec == nil { - out.RawString("null") - } else { - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo1(out, *in.Spec) - } - } - { - const prefix string = ",\"id\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.ID)) - } - { - const prefix string = ",\"name\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Name)) - } - if in.Pod != "" { - const prefix string = ",\"pod\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Pod)) - } - if in.Namespace != "" { - const prefix string = ",\"namespace\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Namespace)) - } - if true { - const prefix string = ",\"idMappingsOptions\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComContainersStorage(out, in.IDMappings) - } - if in.RootfsImageID != "" { - const prefix string = ",\"rootfsImageID\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.RootfsImageID)) - } - if in.RootfsImageName != "" { - const prefix string = ",\"rootfsImageName\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.RootfsImageName)) - } - if in.Rootfs != "" { - const prefix string = ",\"rootfs\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Rootfs)) - } - { - const prefix string = ",\"imageVolumes\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.ImageVolumes)) - } - if in.ShmDir != "" { - const prefix string = ",\"ShmDir\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.ShmDir)) - } - { - const prefix string = ",\"shmSize\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(in.ShmSize)) - } - { - const prefix string = ",\"staticDir\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.StaticDir)) - } - if len(in.Mounts) != 0 { - const prefix string = ",\"mounts\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v56, v57 := range in.Mounts { - if v56 > 0 { - out.RawByte(',') - } - out.String(string(v57)) - } - out.RawByte(']') - } - } - { - const prefix string = ",\"privileged\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.Privileged)) - } - if in.ProcessLabel != "" { - const prefix string = ",\"ProcessLabel\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.ProcessLabel)) - } - if in.MountLabel != "" { - const prefix string = ",\"MountLabel\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.MountLabel)) - } - if len(in.LabelOpts) != 0 { - const prefix string = ",\"labelopts\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v58, v59 := range in.LabelOpts { - if v58 > 0 { - out.RawByte(',') - } - out.String(string(v59)) - } - out.RawByte(']') - } - } - if in.User != "" { - const prefix string = ",\"user\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.User)) - } - if len(in.Groups) != 0 { - const prefix string = ",\"groups\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v60, v61 := range in.Groups { - if v60 > 0 { - out.RawByte(',') - } - out.String(string(v61)) - } - out.RawByte(']') - } - } - if in.IPCNsCtr != "" { - const prefix string = ",\"ipcNsCtr\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.IPCNsCtr)) - } - if in.MountNsCtr != "" { - const prefix string = ",\"mountNsCtr\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.MountNsCtr)) - } - if in.NetNsCtr != "" { - const prefix string = ",\"netNsCtr\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.NetNsCtr)) - } - if in.PIDNsCtr != "" { - const prefix string = ",\"pidNsCtr\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.PIDNsCtr)) - } - if in.UserNsCtr != "" { - const prefix string = ",\"userNsCtr\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.UserNsCtr)) - } - if in.UTSNsCtr != "" { - const prefix string = ",\"utsNsCtr\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.UTSNsCtr)) - } - if in.CgroupNsCtr != "" { - const prefix string = ",\"cgroupNsCtr\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.CgroupNsCtr)) - } - { - const prefix string = ",\"Dependencies\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.Dependencies == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { - out.RawString("null") - } else { - out.RawByte('[') - for v62, v63 := range in.Dependencies { - if v62 > 0 { - out.RawByte(',') - } - out.String(string(v63)) - } - out.RawByte(']') - } - } - { - const prefix string = ",\"createNetNS\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.CreateNetNS)) - } - { - const prefix string = ",\"staticIP\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.RawText((in.StaticIP).MarshalText()) - } - if len(in.PortMappings) != 0 { - const prefix string = ",\"portMappings\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v64, v65 := range in.PortMappings { - if v64 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComCriOOcicniPkgOcicni(out, v65) - } - out.RawByte(']') - } - } - if len(in.DNSServer) != 0 { - const prefix string = ",\"dnsServer\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v66, v67 := range in.DNSServer { - if v66 > 0 { - out.RawByte(',') - } - out.RawText((v67).MarshalText()) - } - out.RawByte(']') - } - } - if len(in.DNSSearch) != 0 { - const prefix string = ",\"dnsSearch\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v68, v69 := range in.DNSSearch { - if v68 > 0 { - out.RawByte(',') - } - out.String(string(v69)) - } - out.RawByte(']') - } - } - if len(in.DNSOption) != 0 { - const prefix string = ",\"dnsOption\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v70, v71 := range in.DNSOption { - if v70 > 0 { - out.RawByte(',') - } - out.String(string(v71)) - } - out.RawByte(']') - } - } - if len(in.HostAdd) != 0 { - const prefix string = ",\"hostsAdd\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v72, v73 := range in.HostAdd { - if v72 > 0 { - out.RawByte(',') - } - out.String(string(v73)) - } - out.RawByte(']') - } - } - if len(in.Networks) != 0 { - const prefix string = ",\"networks\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v74, v75 := range in.Networks { - if v74 > 0 { - out.RawByte(',') - } - out.String(string(v75)) - } - out.RawByte(']') - } - } - if in.NetMode != "" { - const prefix string = ",\"networkMode\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.NetMode)) - } - if len(in.UserVolumes) != 0 { - const prefix string = ",\"userVolumes\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v76, v77 := range in.UserVolumes { - if v76 > 0 { - out.RawByte(',') - } - out.String(string(v77)) - } - out.RawByte(']') - } - } - if len(in.Entrypoint) != 0 { - const prefix string = ",\"entrypoint\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v78, v79 := range in.Entrypoint { - if v78 > 0 { - out.RawByte(',') - } - out.String(string(v79)) - } - out.RawByte(']') - } - } - if len(in.Command) != 0 { - const prefix string = ",\"command\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v80, v81 := range in.Command { - if v80 > 0 { - out.RawByte(',') - } - out.String(string(v81)) - } - out.RawByte(']') - } - } - if in.Stdin { - const prefix string = ",\"stdin\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.Stdin)) - } - if len(in.Labels) != 0 { - const prefix string = ",\"labels\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('{') - v82First := true - for v82Name, v82Value := range in.Labels { - if v82First { - v82First = false - } else { - out.RawByte(',') - } - out.String(string(v82Name)) - out.RawByte(':') - out.String(string(v82Value)) - } - out.RawByte('}') - } - } - if in.StopSignal != 0 { - const prefix string = ",\"stopSignal\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint(uint(in.StopSignal)) - } - if in.StopTimeout != 0 { - const prefix string = ",\"stopTimeout\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint(uint(in.StopTimeout)) - } - { - const prefix string = ",\"createdTime\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Raw((in.CreatedTime).MarshalJSON()) - } - { - const prefix string = ",\"cgroupParent\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.CgroupParent)) - } - { - const prefix string = ",\"logPath\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.LogPath)) - } - if in.ConmonPidFile != "" { - const prefix string = ",\"conmonPidFile\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.ConmonPidFile)) - } - { - const prefix string = ",\"postConfigureNetNS\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.PostConfigureNetNS)) - } - if len(in.ExitCommand) != 0 { - const prefix string = ",\"exitCommand\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v83, v84 := range in.ExitCommand { - if v83 > 0 { - out.RawByte(',') - } - out.String(string(v84)) - } - out.RawByte(']') - } - } - { - const prefix string = ",\"LocalVolumes\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.LocalVolumes == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { - out.RawString("null") - } else { - out.RawByte('[') - for v85, v86 := range in.LocalVolumes { - if v85 > 0 { - out.RawByte(',') - } - out.String(string(v86)) - } - out.RawByte(']') - } - } - { - const prefix string = ",\"pause\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.IsInfra)) - } - { - const prefix string = ",\"systemd\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.Systemd)) - } - out.RawByte('}') -} - -// MarshalJSON supports json.Marshaler interface -func (v Config) MarshalJSON() ([]byte, error) { - w := jwriter.Writer{} - easyjson1dbef17bEncodeGithubComContainersLibpodLibpod2(&w, v) - return w.Buffer.BuildBytes(), w.Error -} - -// MarshalEasyJSON supports easyjson.Marshaler interface -func (v Config) MarshalEasyJSON(w *jwriter.Writer) { - easyjson1dbef17bEncodeGithubComContainersLibpodLibpod2(w, v) -} - -// UnmarshalJSON supports json.Unmarshaler interface -func (v *Config) UnmarshalJSON(data []byte) error { - r := jlexer.Lexer{Data: data} - easyjson1dbef17bDecodeGithubComContainersLibpodLibpod2(&r, v) - return r.Error() -} - -// UnmarshalEasyJSON supports easyjson.Unmarshaler interface -func (v *Config) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjson1dbef17bDecodeGithubComContainersLibpodLibpod2(l, v) -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComCriOOcicniPkgOcicni(in *jlexer.Lexer, out *ocicni.PortMapping) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "hostPort": - out.HostPort = int32(in.Int32()) - case "containerPort": - out.ContainerPort = int32(in.Int32()) - case "protocol": - out.Protocol = string(in.String()) - case "hostIP": - out.HostIP = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComCriOOcicniPkgOcicni(out *jwriter.Writer, in ocicni.PortMapping) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"hostPort\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int32(int32(in.HostPort)) - } - { - const prefix string = ",\"containerPort\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int32(int32(in.ContainerPort)) - } - { - const prefix string = ",\"protocol\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Protocol)) - } - { - const prefix string = ",\"hostIP\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.HostIP)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComContainersStorage(in *jlexer.Lexer, out *storage.IDMappingOptions) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "HostUIDMapping": - out.HostUIDMapping = bool(in.Bool()) - case "HostGIDMapping": - out.HostGIDMapping = bool(in.Bool()) - case "UIDMap": - if in.IsNull() { - in.Skip() - out.UIDMap = nil - } else { - in.Delim('[') - if out.UIDMap == nil { - if !in.IsDelim(']') { - out.UIDMap = make([]idtools.IDMap, 0, 2) - } else { - out.UIDMap = []idtools.IDMap{} - } - } else { - out.UIDMap = (out.UIDMap)[:0] - } - for !in.IsDelim(']') { - var v87 idtools.IDMap - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComContainersStoragePkgIdtools(in, &v87) - out.UIDMap = append(out.UIDMap, v87) - in.WantComma() - } - in.Delim(']') - } - case "GIDMap": - if in.IsNull() { - in.Skip() - out.GIDMap = nil - } else { - in.Delim('[') - if out.GIDMap == nil { - if !in.IsDelim(']') { - out.GIDMap = make([]idtools.IDMap, 0, 2) - } else { - out.GIDMap = []idtools.IDMap{} - } - } else { - out.GIDMap = (out.GIDMap)[:0] - } - for !in.IsDelim(']') { - var v88 idtools.IDMap - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComContainersStoragePkgIdtools(in, &v88) - out.GIDMap = append(out.GIDMap, v88) - in.WantComma() - } - in.Delim(']') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComContainersStorage(out *jwriter.Writer, in storage.IDMappingOptions) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"HostUIDMapping\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.HostUIDMapping)) - } - { - const prefix string = ",\"HostGIDMapping\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.HostGIDMapping)) - } - { - const prefix string = ",\"UIDMap\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.UIDMap == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { - out.RawString("null") - } else { - out.RawByte('[') - for v89, v90 := range in.UIDMap { - if v89 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComContainersStoragePkgIdtools(out, v90) - } - out.RawByte(']') - } - } - { - const prefix string = ",\"GIDMap\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.GIDMap == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { - out.RawString("null") - } else { - out.RawByte('[') - for v91, v92 := range in.GIDMap { - if v91 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComContainersStoragePkgIdtools(out, v92) - } - out.RawByte(']') - } - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComContainersStoragePkgIdtools(in *jlexer.Lexer, out *idtools.IDMap) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "container_id": - out.ContainerID = int(in.Int()) - case "host_id": - out.HostID = int(in.Int()) - case "size": - out.Size = int(in.Int()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComContainersStoragePkgIdtools(out *jwriter.Writer, in idtools.IDMap) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"container_id\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int(int(in.ContainerID)) - } - { - const prefix string = ",\"host_id\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int(int(in.HostID)) - } - { - const prefix string = ",\"size\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int(int(in.Size)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo1(in *jlexer.Lexer, out *specs_go.Spec) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "ociVersion": - out.Version = string(in.String()) - case "process": - if in.IsNull() { - in.Skip() - out.Process = nil - } else { - if out.Process == nil { - out.Process = new(specs_go.Process) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo2(in, &*out.Process) - } - case "root": - if in.IsNull() { - in.Skip() - out.Root = nil - } else { - if out.Root == nil { - out.Root = new(specs_go.Root) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo3(in, &*out.Root) - } - case "hostname": - out.Hostname = string(in.String()) - case "mounts": - if in.IsNull() { - in.Skip() - out.Mounts = nil - } else { - in.Delim('[') - if out.Mounts == nil { - if !in.IsDelim(']') { - out.Mounts = make([]specs_go.Mount, 0, 1) - } else { - out.Mounts = []specs_go.Mount{} - } - } else { - out.Mounts = (out.Mounts)[:0] - } - for !in.IsDelim(']') { - var v93 specs_go.Mount - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo4(in, &v93) - out.Mounts = append(out.Mounts, v93) - in.WantComma() - } - in.Delim(']') - } - case "hooks": - if in.IsNull() { - in.Skip() - out.Hooks = nil - } else { - if out.Hooks == nil { - out.Hooks = new(specs_go.Hooks) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo5(in, &*out.Hooks) - } - case "annotations": - if in.IsNull() { - in.Skip() - } else { - in.Delim('{') - if !in.IsDelim('}') { - out.Annotations = make(map[string]string) - } else { - out.Annotations = nil - } - for !in.IsDelim('}') { - key := string(in.String()) - in.WantColon() - var v94 string - v94 = string(in.String()) - (out.Annotations)[key] = v94 - in.WantComma() - } - in.Delim('}') - } - case "linux": - if in.IsNull() { - in.Skip() - out.Linux = nil - } else { - if out.Linux == nil { - out.Linux = new(specs_go.Linux) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo6(in, &*out.Linux) - } - case "solaris": - if in.IsNull() { - in.Skip() - out.Solaris = nil - } else { - if out.Solaris == nil { - out.Solaris = new(specs_go.Solaris) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo7(in, &*out.Solaris) - } - case "windows": - if in.IsNull() { - in.Skip() - out.Windows = nil - } else { - if out.Windows == nil { - out.Windows = new(specs_go.Windows) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo8(in, &*out.Windows) - } - case "vm": - if in.IsNull() { - in.Skip() - out.VM = nil - } else { - if out.VM == nil { - out.VM = new(specs_go.VM) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo9(in, &*out.VM) - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo1(out *jwriter.Writer, in specs_go.Spec) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"ociVersion\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Version)) - } - if in.Process != nil { - const prefix string = ",\"process\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo2(out, *in.Process) - } - if in.Root != nil { - const prefix string = ",\"root\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo3(out, *in.Root) - } - if in.Hostname != "" { - const prefix string = ",\"hostname\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Hostname)) - } - if len(in.Mounts) != 0 { - const prefix string = ",\"mounts\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v95, v96 := range in.Mounts { - if v95 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo4(out, v96) - } - out.RawByte(']') - } - } - if in.Hooks != nil { - const prefix string = ",\"hooks\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo5(out, *in.Hooks) - } - if len(in.Annotations) != 0 { - const prefix string = ",\"annotations\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('{') - v97First := true - for v97Name, v97Value := range in.Annotations { - if v97First { - v97First = false - } else { - out.RawByte(',') - } - out.String(string(v97Name)) - out.RawByte(':') - out.String(string(v97Value)) - } - out.RawByte('}') - } - } - if in.Linux != nil { - const prefix string = ",\"linux\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo6(out, *in.Linux) - } - if in.Solaris != nil { - const prefix string = ",\"solaris\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo7(out, *in.Solaris) - } - if in.Windows != nil { - const prefix string = ",\"windows\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo8(out, *in.Windows) - } - if in.VM != nil { - const prefix string = ",\"vm\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo9(out, *in.VM) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo9(in *jlexer.Lexer, out *specs_go.VM) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "hypervisor": - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo10(in, &out.Hypervisor) - case "kernel": - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo11(in, &out.Kernel) - case "image": - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo12(in, &out.Image) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo9(out *jwriter.Writer, in specs_go.VM) { - out.RawByte('{') - first := true - _ = first - if true { - const prefix string = ",\"hypervisor\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo10(out, in.Hypervisor) - } - { - const prefix string = ",\"kernel\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo11(out, in.Kernel) - } - if true { - const prefix string = ",\"image\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo12(out, in.Image) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo12(in *jlexer.Lexer, out *specs_go.VMImage) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "path": - out.Path = string(in.String()) - case "format": - out.Format = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo12(out *jwriter.Writer, in specs_go.VMImage) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"path\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Path)) - } - { - const prefix string = ",\"format\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Format)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo11(in *jlexer.Lexer, out *specs_go.VMKernel) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "path": - out.Path = string(in.String()) - case "parameters": - out.Parameters = string(in.String()) - case "initrd": - out.InitRD = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo11(out *jwriter.Writer, in specs_go.VMKernel) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"path\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Path)) - } - if in.Parameters != "" { - const prefix string = ",\"parameters\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Parameters)) - } - if in.InitRD != "" { - const prefix string = ",\"initrd\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.InitRD)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo10(in *jlexer.Lexer, out *specs_go.VMHypervisor) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "path": - out.Path = string(in.String()) - case "parameters": - out.Parameters = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo10(out *jwriter.Writer, in specs_go.VMHypervisor) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"path\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Path)) - } - if in.Parameters != "" { - const prefix string = ",\"parameters\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Parameters)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo8(in *jlexer.Lexer, out *specs_go.Windows) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "layerFolders": - if in.IsNull() { - in.Skip() - out.LayerFolders = nil - } else { - in.Delim('[') - if out.LayerFolders == nil { - if !in.IsDelim(']') { - out.LayerFolders = make([]string, 0, 4) - } else { - out.LayerFolders = []string{} - } - } else { - out.LayerFolders = (out.LayerFolders)[:0] - } - for !in.IsDelim(']') { - var v98 string - v98 = string(in.String()) - out.LayerFolders = append(out.LayerFolders, v98) - in.WantComma() - } - in.Delim(']') - } - case "devices": - if in.IsNull() { - in.Skip() - out.Devices = nil - } else { - in.Delim('[') - if out.Devices == nil { - if !in.IsDelim(']') { - out.Devices = make([]specs_go.WindowsDevice, 0, 2) - } else { - out.Devices = []specs_go.WindowsDevice{} - } - } else { - out.Devices = (out.Devices)[:0] - } - for !in.IsDelim(']') { - var v99 specs_go.WindowsDevice - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo13(in, &v99) - out.Devices = append(out.Devices, v99) - in.WantComma() - } - in.Delim(']') - } - case "resources": - if in.IsNull() { - in.Skip() - out.Resources = nil - } else { - if out.Resources == nil { - out.Resources = new(specs_go.WindowsResources) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo14(in, &*out.Resources) - } - case "credentialSpec": - if m, ok := out.CredentialSpec.(easyjson.Unmarshaler); ok { - m.UnmarshalEasyJSON(in) - } else if m, ok := out.CredentialSpec.(json.Unmarshaler); ok { - _ = m.UnmarshalJSON(in.Raw()) - } else { - out.CredentialSpec = in.Interface() - } - case "servicing": - out.Servicing = bool(in.Bool()) - case "ignoreFlushesDuringBoot": - out.IgnoreFlushesDuringBoot = bool(in.Bool()) - case "hyperv": - if in.IsNull() { - in.Skip() - out.HyperV = nil - } else { - if out.HyperV == nil { - out.HyperV = new(specs_go.WindowsHyperV) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo15(in, &*out.HyperV) - } - case "network": - if in.IsNull() { - in.Skip() - out.Network = nil - } else { - if out.Network == nil { - out.Network = new(specs_go.WindowsNetwork) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo16(in, &*out.Network) - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo8(out *jwriter.Writer, in specs_go.Windows) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"layerFolders\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.LayerFolders == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { - out.RawString("null") - } else { - out.RawByte('[') - for v100, v101 := range in.LayerFolders { - if v100 > 0 { - out.RawByte(',') - } - out.String(string(v101)) - } - out.RawByte(']') - } - } - if len(in.Devices) != 0 { - const prefix string = ",\"devices\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v102, v103 := range in.Devices { - if v102 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo13(out, v103) - } - out.RawByte(']') - } - } - if in.Resources != nil { - const prefix string = ",\"resources\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo14(out, *in.Resources) - } - if in.CredentialSpec != nil { - const prefix string = ",\"credentialSpec\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if m, ok := in.CredentialSpec.(easyjson.Marshaler); ok { - m.MarshalEasyJSON(out) - } else if m, ok := in.CredentialSpec.(json.Marshaler); ok { - out.Raw(m.MarshalJSON()) - } else { - out.Raw(json.Marshal(in.CredentialSpec)) - } - } - if in.Servicing { - const prefix string = ",\"servicing\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.Servicing)) - } - if in.IgnoreFlushesDuringBoot { - const prefix string = ",\"ignoreFlushesDuringBoot\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.IgnoreFlushesDuringBoot)) - } - if in.HyperV != nil { - const prefix string = ",\"hyperv\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo15(out, *in.HyperV) - } - if in.Network != nil { - const prefix string = ",\"network\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo16(out, *in.Network) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo16(in *jlexer.Lexer, out *specs_go.WindowsNetwork) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "endpointList": - if in.IsNull() { - in.Skip() - out.EndpointList = nil - } else { - in.Delim('[') - if out.EndpointList == nil { - if !in.IsDelim(']') { - out.EndpointList = make([]string, 0, 4) - } else { - out.EndpointList = []string{} - } - } else { - out.EndpointList = (out.EndpointList)[:0] - } - for !in.IsDelim(']') { - var v104 string - v104 = string(in.String()) - out.EndpointList = append(out.EndpointList, v104) - in.WantComma() - } - in.Delim(']') - } - case "allowUnqualifiedDNSQuery": - out.AllowUnqualifiedDNSQuery = bool(in.Bool()) - case "DNSSearchList": - if in.IsNull() { - in.Skip() - out.DNSSearchList = nil - } else { - in.Delim('[') - if out.DNSSearchList == nil { - if !in.IsDelim(']') { - out.DNSSearchList = make([]string, 0, 4) - } else { - out.DNSSearchList = []string{} - } - } else { - out.DNSSearchList = (out.DNSSearchList)[:0] - } - for !in.IsDelim(']') { - var v105 string - v105 = string(in.String()) - out.DNSSearchList = append(out.DNSSearchList, v105) - in.WantComma() - } - in.Delim(']') - } - case "networkSharedContainerName": - out.NetworkSharedContainerName = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo16(out *jwriter.Writer, in specs_go.WindowsNetwork) { - out.RawByte('{') - first := true - _ = first - if len(in.EndpointList) != 0 { - const prefix string = ",\"endpointList\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v106, v107 := range in.EndpointList { - if v106 > 0 { - out.RawByte(',') - } - out.String(string(v107)) - } - out.RawByte(']') - } - } - if in.AllowUnqualifiedDNSQuery { - const prefix string = ",\"allowUnqualifiedDNSQuery\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.AllowUnqualifiedDNSQuery)) - } - if len(in.DNSSearchList) != 0 { - const prefix string = ",\"DNSSearchList\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v108, v109 := range in.DNSSearchList { - if v108 > 0 { - out.RawByte(',') - } - out.String(string(v109)) - } - out.RawByte(']') - } - } - if in.NetworkSharedContainerName != "" { - const prefix string = ",\"networkSharedContainerName\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.NetworkSharedContainerName)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo15(in *jlexer.Lexer, out *specs_go.WindowsHyperV) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "utilityVMPath": - out.UtilityVMPath = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo15(out *jwriter.Writer, in specs_go.WindowsHyperV) { - out.RawByte('{') - first := true - _ = first - if in.UtilityVMPath != "" { - const prefix string = ",\"utilityVMPath\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.UtilityVMPath)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo14(in *jlexer.Lexer, out *specs_go.WindowsResources) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "memory": - if in.IsNull() { - in.Skip() - out.Memory = nil - } else { - if out.Memory == nil { - out.Memory = new(specs_go.WindowsMemoryResources) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo17(in, &*out.Memory) - } - case "cpu": - if in.IsNull() { - in.Skip() - out.CPU = nil - } else { - if out.CPU == nil { - out.CPU = new(specs_go.WindowsCPUResources) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo18(in, &*out.CPU) - } - case "storage": - if in.IsNull() { - in.Skip() - out.Storage = nil - } else { - if out.Storage == nil { - out.Storage = new(specs_go.WindowsStorageResources) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo19(in, &*out.Storage) - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo14(out *jwriter.Writer, in specs_go.WindowsResources) { - out.RawByte('{') - first := true - _ = first - if in.Memory != nil { - const prefix string = ",\"memory\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo17(out, *in.Memory) - } - if in.CPU != nil { - const prefix string = ",\"cpu\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo18(out, *in.CPU) - } - if in.Storage != nil { - const prefix string = ",\"storage\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo19(out, *in.Storage) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo19(in *jlexer.Lexer, out *specs_go.WindowsStorageResources) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "iops": - if in.IsNull() { - in.Skip() - out.Iops = nil - } else { - if out.Iops == nil { - out.Iops = new(uint64) - } - *out.Iops = uint64(in.Uint64()) - } - case "bps": - if in.IsNull() { - in.Skip() - out.Bps = nil - } else { - if out.Bps == nil { - out.Bps = new(uint64) - } - *out.Bps = uint64(in.Uint64()) - } - case "sandboxSize": - if in.IsNull() { - in.Skip() - out.SandboxSize = nil - } else { - if out.SandboxSize == nil { - out.SandboxSize = new(uint64) - } - *out.SandboxSize = uint64(in.Uint64()) - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo19(out *jwriter.Writer, in specs_go.WindowsStorageResources) { - out.RawByte('{') - first := true - _ = first - if in.Iops != nil { - const prefix string = ",\"iops\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(*in.Iops)) - } - if in.Bps != nil { - const prefix string = ",\"bps\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(*in.Bps)) - } - if in.SandboxSize != nil { - const prefix string = ",\"sandboxSize\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(*in.SandboxSize)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo18(in *jlexer.Lexer, out *specs_go.WindowsCPUResources) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "count": - if in.IsNull() { - in.Skip() - out.Count = nil - } else { - if out.Count == nil { - out.Count = new(uint64) - } - *out.Count = uint64(in.Uint64()) - } - case "shares": - if in.IsNull() { - in.Skip() - out.Shares = nil - } else { - if out.Shares == nil { - out.Shares = new(uint16) - } - *out.Shares = uint16(in.Uint16()) - } - case "maximum": - if in.IsNull() { - in.Skip() - out.Maximum = nil - } else { - if out.Maximum == nil { - out.Maximum = new(uint16) - } - *out.Maximum = uint16(in.Uint16()) - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo18(out *jwriter.Writer, in specs_go.WindowsCPUResources) { - out.RawByte('{') - first := true - _ = first - if in.Count != nil { - const prefix string = ",\"count\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(*in.Count)) - } - if in.Shares != nil { - const prefix string = ",\"shares\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint16(uint16(*in.Shares)) - } - if in.Maximum != nil { - const prefix string = ",\"maximum\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint16(uint16(*in.Maximum)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo17(in *jlexer.Lexer, out *specs_go.WindowsMemoryResources) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "limit": - if in.IsNull() { - in.Skip() - out.Limit = nil - } else { - if out.Limit == nil { - out.Limit = new(uint64) - } - *out.Limit = uint64(in.Uint64()) - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo17(out *jwriter.Writer, in specs_go.WindowsMemoryResources) { - out.RawByte('{') - first := true - _ = first - if in.Limit != nil { - const prefix string = ",\"limit\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(*in.Limit)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo13(in *jlexer.Lexer, out *specs_go.WindowsDevice) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "id": - out.ID = string(in.String()) - case "idType": - out.IDType = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo13(out *jwriter.Writer, in specs_go.WindowsDevice) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"id\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.ID)) - } - { - const prefix string = ",\"idType\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.IDType)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo7(in *jlexer.Lexer, out *specs_go.Solaris) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "milestone": - out.Milestone = string(in.String()) - case "limitpriv": - out.LimitPriv = string(in.String()) - case "maxShmMemory": - out.MaxShmMemory = string(in.String()) - case "anet": - if in.IsNull() { - in.Skip() - out.Anet = nil - } else { - in.Delim('[') - if out.Anet == nil { - if !in.IsDelim(']') { - out.Anet = make([]specs_go.SolarisAnet, 0, 1) - } else { - out.Anet = []specs_go.SolarisAnet{} - } - } else { - out.Anet = (out.Anet)[:0] - } - for !in.IsDelim(']') { - var v110 specs_go.SolarisAnet - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo20(in, &v110) - out.Anet = append(out.Anet, v110) - in.WantComma() - } - in.Delim(']') - } - case "cappedCPU": - if in.IsNull() { - in.Skip() - out.CappedCPU = nil - } else { - if out.CappedCPU == nil { - out.CappedCPU = new(specs_go.SolarisCappedCPU) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo21(in, &*out.CappedCPU) - } - case "cappedMemory": - if in.IsNull() { - in.Skip() - out.CappedMemory = nil - } else { - if out.CappedMemory == nil { - out.CappedMemory = new(specs_go.SolarisCappedMemory) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo22(in, &*out.CappedMemory) - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo7(out *jwriter.Writer, in specs_go.Solaris) { - out.RawByte('{') - first := true - _ = first - if in.Milestone != "" { - const prefix string = ",\"milestone\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Milestone)) - } - if in.LimitPriv != "" { - const prefix string = ",\"limitpriv\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.LimitPriv)) - } - if in.MaxShmMemory != "" { - const prefix string = ",\"maxShmMemory\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.MaxShmMemory)) - } - if len(in.Anet) != 0 { - const prefix string = ",\"anet\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v111, v112 := range in.Anet { - if v111 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo20(out, v112) - } - out.RawByte(']') - } - } - if in.CappedCPU != nil { - const prefix string = ",\"cappedCPU\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo21(out, *in.CappedCPU) - } - if in.CappedMemory != nil { - const prefix string = ",\"cappedMemory\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo22(out, *in.CappedMemory) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo22(in *jlexer.Lexer, out *specs_go.SolarisCappedMemory) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "physical": - out.Physical = string(in.String()) - case "swap": - out.Swap = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo22(out *jwriter.Writer, in specs_go.SolarisCappedMemory) { - out.RawByte('{') - first := true - _ = first - if in.Physical != "" { - const prefix string = ",\"physical\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Physical)) - } - if in.Swap != "" { - const prefix string = ",\"swap\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Swap)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo21(in *jlexer.Lexer, out *specs_go.SolarisCappedCPU) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "ncpus": - out.Ncpus = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo21(out *jwriter.Writer, in specs_go.SolarisCappedCPU) { - out.RawByte('{') - first := true - _ = first - if in.Ncpus != "" { - const prefix string = ",\"ncpus\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Ncpus)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo20(in *jlexer.Lexer, out *specs_go.SolarisAnet) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "linkname": - out.Linkname = string(in.String()) - case "lowerLink": - out.Lowerlink = string(in.String()) - case "allowedAddress": - out.Allowedaddr = string(in.String()) - case "configureAllowedAddress": - out.Configallowedaddr = string(in.String()) - case "defrouter": - out.Defrouter = string(in.String()) - case "linkProtection": - out.Linkprotection = string(in.String()) - case "macAddress": - out.Macaddress = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo20(out *jwriter.Writer, in specs_go.SolarisAnet) { - out.RawByte('{') - first := true - _ = first - if in.Linkname != "" { - const prefix string = ",\"linkname\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Linkname)) - } - if in.Lowerlink != "" { - const prefix string = ",\"lowerLink\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Lowerlink)) - } - if in.Allowedaddr != "" { - const prefix string = ",\"allowedAddress\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Allowedaddr)) - } - if in.Configallowedaddr != "" { - const prefix string = ",\"configureAllowedAddress\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Configallowedaddr)) - } - if in.Defrouter != "" { - const prefix string = ",\"defrouter\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Defrouter)) - } - if in.Linkprotection != "" { - const prefix string = ",\"linkProtection\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Linkprotection)) - } - if in.Macaddress != "" { - const prefix string = ",\"macAddress\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Macaddress)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo6(in *jlexer.Lexer, out *specs_go.Linux) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "uidMappings": - if in.IsNull() { - in.Skip() - out.UIDMappings = nil - } else { - in.Delim('[') - if out.UIDMappings == nil { - if !in.IsDelim(']') { - out.UIDMappings = make([]specs_go.LinuxIDMapping, 0, 5) - } else { - out.UIDMappings = []specs_go.LinuxIDMapping{} - } - } else { - out.UIDMappings = (out.UIDMappings)[:0] - } - for !in.IsDelim(']') { - var v113 specs_go.LinuxIDMapping - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo23(in, &v113) - out.UIDMappings = append(out.UIDMappings, v113) - in.WantComma() - } - in.Delim(']') - } - case "gidMappings": - if in.IsNull() { - in.Skip() - out.GIDMappings = nil - } else { - in.Delim('[') - if out.GIDMappings == nil { - if !in.IsDelim(']') { - out.GIDMappings = make([]specs_go.LinuxIDMapping, 0, 5) - } else { - out.GIDMappings = []specs_go.LinuxIDMapping{} - } - } else { - out.GIDMappings = (out.GIDMappings)[:0] - } - for !in.IsDelim(']') { - var v114 specs_go.LinuxIDMapping - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo23(in, &v114) - out.GIDMappings = append(out.GIDMappings, v114) - in.WantComma() - } - in.Delim(']') - } - case "sysctl": - if in.IsNull() { - in.Skip() - } else { - in.Delim('{') - if !in.IsDelim('}') { - out.Sysctl = make(map[string]string) - } else { - out.Sysctl = nil - } - for !in.IsDelim('}') { - key := string(in.String()) - in.WantColon() - var v115 string - v115 = string(in.String()) - (out.Sysctl)[key] = v115 - in.WantComma() - } - in.Delim('}') - } - case "resources": - if in.IsNull() { - in.Skip() - out.Resources = nil - } else { - if out.Resources == nil { - out.Resources = new(specs_go.LinuxResources) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo24(in, &*out.Resources) - } - case "cgroupsPath": - out.CgroupsPath = string(in.String()) - case "namespaces": - if in.IsNull() { - in.Skip() - out.Namespaces = nil - } else { - in.Delim('[') - if out.Namespaces == nil { - if !in.IsDelim(']') { - out.Namespaces = make([]specs_go.LinuxNamespace, 0, 2) - } else { - out.Namespaces = []specs_go.LinuxNamespace{} - } - } else { - out.Namespaces = (out.Namespaces)[:0] - } - for !in.IsDelim(']') { - var v116 specs_go.LinuxNamespace - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo25(in, &v116) - out.Namespaces = append(out.Namespaces, v116) - in.WantComma() - } - in.Delim(']') - } - case "devices": - if in.IsNull() { - in.Skip() - out.Devices = nil - } else { - in.Delim('[') - if out.Devices == nil { - if !in.IsDelim(']') { - out.Devices = make([]specs_go.LinuxDevice, 0, 1) - } else { - out.Devices = []specs_go.LinuxDevice{} - } - } else { - out.Devices = (out.Devices)[:0] - } - for !in.IsDelim(']') { - var v117 specs_go.LinuxDevice - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo26(in, &v117) - out.Devices = append(out.Devices, v117) - in.WantComma() - } - in.Delim(']') - } - case "seccomp": - if in.IsNull() { - in.Skip() - out.Seccomp = nil - } else { - if out.Seccomp == nil { - out.Seccomp = new(specs_go.LinuxSeccomp) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo27(in, &*out.Seccomp) - } - case "rootfsPropagation": - out.RootfsPropagation = string(in.String()) - case "maskedPaths": - if in.IsNull() { - in.Skip() - out.MaskedPaths = nil - } else { - in.Delim('[') - if out.MaskedPaths == nil { - if !in.IsDelim(']') { - out.MaskedPaths = make([]string, 0, 4) - } else { - out.MaskedPaths = []string{} - } - } else { - out.MaskedPaths = (out.MaskedPaths)[:0] - } - for !in.IsDelim(']') { - var v118 string - v118 = string(in.String()) - out.MaskedPaths = append(out.MaskedPaths, v118) - in.WantComma() - } - in.Delim(']') - } - case "readonlyPaths": - if in.IsNull() { - in.Skip() - out.ReadonlyPaths = nil - } else { - in.Delim('[') - if out.ReadonlyPaths == nil { - if !in.IsDelim(']') { - out.ReadonlyPaths = make([]string, 0, 4) - } else { - out.ReadonlyPaths = []string{} - } - } else { - out.ReadonlyPaths = (out.ReadonlyPaths)[:0] - } - for !in.IsDelim(']') { - var v119 string - v119 = string(in.String()) - out.ReadonlyPaths = append(out.ReadonlyPaths, v119) - in.WantComma() - } - in.Delim(']') - } - case "mountLabel": - out.MountLabel = string(in.String()) - case "intelRdt": - if in.IsNull() { - in.Skip() - out.IntelRdt = nil - } else { - if out.IntelRdt == nil { - out.IntelRdt = new(specs_go.LinuxIntelRdt) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo28(in, &*out.IntelRdt) - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo6(out *jwriter.Writer, in specs_go.Linux) { - out.RawByte('{') - first := true - _ = first - if len(in.UIDMappings) != 0 { - const prefix string = ",\"uidMappings\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v120, v121 := range in.UIDMappings { - if v120 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo23(out, v121) - } - out.RawByte(']') - } - } - if len(in.GIDMappings) != 0 { - const prefix string = ",\"gidMappings\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v122, v123 := range in.GIDMappings { - if v122 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo23(out, v123) - } - out.RawByte(']') - } - } - if len(in.Sysctl) != 0 { - const prefix string = ",\"sysctl\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('{') - v124First := true - for v124Name, v124Value := range in.Sysctl { - if v124First { - v124First = false - } else { - out.RawByte(',') - } - out.String(string(v124Name)) - out.RawByte(':') - out.String(string(v124Value)) - } - out.RawByte('}') - } - } - if in.Resources != nil { - const prefix string = ",\"resources\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo24(out, *in.Resources) - } - if in.CgroupsPath != "" { - const prefix string = ",\"cgroupsPath\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.CgroupsPath)) - } - if len(in.Namespaces) != 0 { - const prefix string = ",\"namespaces\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v125, v126 := range in.Namespaces { - if v125 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo25(out, v126) - } - out.RawByte(']') - } - } - if len(in.Devices) != 0 { - const prefix string = ",\"devices\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v127, v128 := range in.Devices { - if v127 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo26(out, v128) - } - out.RawByte(']') - } - } - if in.Seccomp != nil { - const prefix string = ",\"seccomp\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo27(out, *in.Seccomp) - } - if in.RootfsPropagation != "" { - const prefix string = ",\"rootfsPropagation\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.RootfsPropagation)) - } - if len(in.MaskedPaths) != 0 { - const prefix string = ",\"maskedPaths\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v129, v130 := range in.MaskedPaths { - if v129 > 0 { - out.RawByte(',') - } - out.String(string(v130)) - } - out.RawByte(']') - } - } - if len(in.ReadonlyPaths) != 0 { - const prefix string = ",\"readonlyPaths\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v131, v132 := range in.ReadonlyPaths { - if v131 > 0 { - out.RawByte(',') - } - out.String(string(v132)) - } - out.RawByte(']') - } - } - if in.MountLabel != "" { - const prefix string = ",\"mountLabel\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.MountLabel)) - } - if in.IntelRdt != nil { - const prefix string = ",\"intelRdt\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo28(out, *in.IntelRdt) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo28(in *jlexer.Lexer, out *specs_go.LinuxIntelRdt) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "l3CacheSchema": - out.L3CacheSchema = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo28(out *jwriter.Writer, in specs_go.LinuxIntelRdt) { - out.RawByte('{') - first := true - _ = first - if in.L3CacheSchema != "" { - const prefix string = ",\"l3CacheSchema\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.L3CacheSchema)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo27(in *jlexer.Lexer, out *specs_go.LinuxSeccomp) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "defaultAction": - out.DefaultAction = specs_go.LinuxSeccompAction(in.String()) - case "architectures": - if in.IsNull() { - in.Skip() - out.Architectures = nil - } else { - in.Delim('[') - if out.Architectures == nil { - if !in.IsDelim(']') { - out.Architectures = make([]specs_go.Arch, 0, 4) - } else { - out.Architectures = []specs_go.Arch{} - } - } else { - out.Architectures = (out.Architectures)[:0] - } - for !in.IsDelim(']') { - var v133 specs_go.Arch - v133 = specs_go.Arch(in.String()) - out.Architectures = append(out.Architectures, v133) - in.WantComma() - } - in.Delim(']') - } - case "syscalls": - if in.IsNull() { - in.Skip() - out.Syscalls = nil - } else { - in.Delim('[') - if out.Syscalls == nil { - if !in.IsDelim(']') { - out.Syscalls = make([]specs_go.LinuxSyscall, 0, 1) - } else { - out.Syscalls = []specs_go.LinuxSyscall{} - } - } else { - out.Syscalls = (out.Syscalls)[:0] - } - for !in.IsDelim(']') { - var v134 specs_go.LinuxSyscall - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo29(in, &v134) - out.Syscalls = append(out.Syscalls, v134) - in.WantComma() - } - in.Delim(']') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo27(out *jwriter.Writer, in specs_go.LinuxSeccomp) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"defaultAction\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.DefaultAction)) - } - if len(in.Architectures) != 0 { - const prefix string = ",\"architectures\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v135, v136 := range in.Architectures { - if v135 > 0 { - out.RawByte(',') - } - out.String(string(v136)) - } - out.RawByte(']') - } - } - if len(in.Syscalls) != 0 { - const prefix string = ",\"syscalls\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v137, v138 := range in.Syscalls { - if v137 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo29(out, v138) - } - out.RawByte(']') - } - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo29(in *jlexer.Lexer, out *specs_go.LinuxSyscall) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "names": - if in.IsNull() { - in.Skip() - out.Names = nil - } else { - in.Delim('[') - if out.Names == nil { - if !in.IsDelim(']') { - out.Names = make([]string, 0, 4) - } else { - out.Names = []string{} - } - } else { - out.Names = (out.Names)[:0] - } - for !in.IsDelim(']') { - var v139 string - v139 = string(in.String()) - out.Names = append(out.Names, v139) - in.WantComma() - } - in.Delim(']') - } - case "action": - out.Action = specs_go.LinuxSeccompAction(in.String()) - case "args": - if in.IsNull() { - in.Skip() - out.Args = nil - } else { - in.Delim('[') - if out.Args == nil { - if !in.IsDelim(']') { - out.Args = make([]specs_go.LinuxSeccompArg, 0, 1) - } else { - out.Args = []specs_go.LinuxSeccompArg{} - } - } else { - out.Args = (out.Args)[:0] - } - for !in.IsDelim(']') { - var v140 specs_go.LinuxSeccompArg - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo30(in, &v140) - out.Args = append(out.Args, v140) - in.WantComma() - } - in.Delim(']') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo29(out *jwriter.Writer, in specs_go.LinuxSyscall) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"names\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.Names == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { - out.RawString("null") - } else { - out.RawByte('[') - for v141, v142 := range in.Names { - if v141 > 0 { - out.RawByte(',') - } - out.String(string(v142)) - } - out.RawByte(']') - } - } - { - const prefix string = ",\"action\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Action)) - } - if len(in.Args) != 0 { - const prefix string = ",\"args\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v143, v144 := range in.Args { - if v143 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo30(out, v144) - } - out.RawByte(']') - } - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo30(in *jlexer.Lexer, out *specs_go.LinuxSeccompArg) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "index": - out.Index = uint(in.Uint()) - case "value": - out.Value = uint64(in.Uint64()) - case "valueTwo": - out.ValueTwo = uint64(in.Uint64()) - case "op": - out.Op = specs_go.LinuxSeccompOperator(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo30(out *jwriter.Writer, in specs_go.LinuxSeccompArg) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"index\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint(uint(in.Index)) - } - { - const prefix string = ",\"value\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(in.Value)) - } - if in.ValueTwo != 0 { - const prefix string = ",\"valueTwo\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(in.ValueTwo)) - } - { - const prefix string = ",\"op\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Op)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo26(in *jlexer.Lexer, out *specs_go.LinuxDevice) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "path": - out.Path = string(in.String()) - case "type": - out.Type = string(in.String()) - case "major": - out.Major = int64(in.Int64()) - case "minor": - out.Minor = int64(in.Int64()) - case "fileMode": - if in.IsNull() { - in.Skip() - out.FileMode = nil - } else { - if out.FileMode == nil { - out.FileMode = new(os.FileMode) - } - *out.FileMode = os.FileMode(in.Uint32()) - } - case "uid": - if in.IsNull() { - in.Skip() - out.UID = nil - } else { - if out.UID == nil { - out.UID = new(uint32) - } - *out.UID = uint32(in.Uint32()) - } - case "gid": - if in.IsNull() { - in.Skip() - out.GID = nil - } else { - if out.GID == nil { - out.GID = new(uint32) - } - *out.GID = uint32(in.Uint32()) - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo26(out *jwriter.Writer, in specs_go.LinuxDevice) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"path\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Path)) - } - { - const prefix string = ",\"type\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Type)) - } - { - const prefix string = ",\"major\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(in.Major)) - } - { - const prefix string = ",\"minor\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(in.Minor)) - } - if in.FileMode != nil { - const prefix string = ",\"fileMode\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint32(uint32(*in.FileMode)) - } - if in.UID != nil { - const prefix string = ",\"uid\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint32(uint32(*in.UID)) - } - if in.GID != nil { - const prefix string = ",\"gid\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint32(uint32(*in.GID)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo25(in *jlexer.Lexer, out *specs_go.LinuxNamespace) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "type": - out.Type = specs_go.LinuxNamespaceType(in.String()) - case "path": - out.Path = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo25(out *jwriter.Writer, in specs_go.LinuxNamespace) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"type\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Type)) - } - if in.Path != "" { - const prefix string = ",\"path\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Path)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo24(in *jlexer.Lexer, out *specs_go.LinuxResources) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "devices": - if in.IsNull() { - in.Skip() - out.Devices = nil - } else { - in.Delim('[') - if out.Devices == nil { - if !in.IsDelim(']') { - out.Devices = make([]specs_go.LinuxDeviceCgroup, 0, 1) - } else { - out.Devices = []specs_go.LinuxDeviceCgroup{} - } - } else { - out.Devices = (out.Devices)[:0] - } - for !in.IsDelim(']') { - var v145 specs_go.LinuxDeviceCgroup - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo31(in, &v145) - out.Devices = append(out.Devices, v145) - in.WantComma() - } - in.Delim(']') - } - case "memory": - if in.IsNull() { - in.Skip() - out.Memory = nil - } else { - if out.Memory == nil { - out.Memory = new(specs_go.LinuxMemory) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo32(in, &*out.Memory) - } - case "cpu": - if in.IsNull() { - in.Skip() - out.CPU = nil - } else { - if out.CPU == nil { - out.CPU = new(specs_go.LinuxCPU) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo33(in, &*out.CPU) - } - case "pids": - if in.IsNull() { - in.Skip() - out.Pids = nil - } else { - if out.Pids == nil { - out.Pids = new(specs_go.LinuxPids) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo34(in, &*out.Pids) - } - case "blockIO": - if in.IsNull() { - in.Skip() - out.BlockIO = nil - } else { - if out.BlockIO == nil { - out.BlockIO = new(specs_go.LinuxBlockIO) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo35(in, &*out.BlockIO) - } - case "hugepageLimits": - if in.IsNull() { - in.Skip() - out.HugepageLimits = nil - } else { - in.Delim('[') - if out.HugepageLimits == nil { - if !in.IsDelim(']') { - out.HugepageLimits = make([]specs_go.LinuxHugepageLimit, 0, 2) - } else { - out.HugepageLimits = []specs_go.LinuxHugepageLimit{} - } - } else { - out.HugepageLimits = (out.HugepageLimits)[:0] - } - for !in.IsDelim(']') { - var v146 specs_go.LinuxHugepageLimit - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo36(in, &v146) - out.HugepageLimits = append(out.HugepageLimits, v146) - in.WantComma() - } - in.Delim(']') - } - case "network": - if in.IsNull() { - in.Skip() - out.Network = nil - } else { - if out.Network == nil { - out.Network = new(specs_go.LinuxNetwork) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo37(in, &*out.Network) - } - case "rdma": - if in.IsNull() { - in.Skip() - } else { - in.Delim('{') - if !in.IsDelim('}') { - out.Rdma = make(map[string]specs_go.LinuxRdma) - } else { - out.Rdma = nil - } - for !in.IsDelim('}') { - key := string(in.String()) - in.WantColon() - var v147 specs_go.LinuxRdma - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo38(in, &v147) - (out.Rdma)[key] = v147 - in.WantComma() - } - in.Delim('}') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo24(out *jwriter.Writer, in specs_go.LinuxResources) { - out.RawByte('{') - first := true - _ = first - if len(in.Devices) != 0 { - const prefix string = ",\"devices\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v148, v149 := range in.Devices { - if v148 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo31(out, v149) - } - out.RawByte(']') - } - } - if in.Memory != nil { - const prefix string = ",\"memory\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo32(out, *in.Memory) - } - if in.CPU != nil { - const prefix string = ",\"cpu\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo33(out, *in.CPU) - } - if in.Pids != nil { - const prefix string = ",\"pids\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo34(out, *in.Pids) - } - if in.BlockIO != nil { - const prefix string = ",\"blockIO\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo35(out, *in.BlockIO) - } - if len(in.HugepageLimits) != 0 { - const prefix string = ",\"hugepageLimits\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v150, v151 := range in.HugepageLimits { - if v150 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo36(out, v151) - } - out.RawByte(']') - } - } - if in.Network != nil { - const prefix string = ",\"network\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo37(out, *in.Network) - } - if len(in.Rdma) != 0 { - const prefix string = ",\"rdma\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('{') - v152First := true - for v152Name, v152Value := range in.Rdma { - if v152First { - v152First = false - } else { - out.RawByte(',') - } - out.String(string(v152Name)) - out.RawByte(':') - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo38(out, v152Value) - } - out.RawByte('}') - } - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo38(in *jlexer.Lexer, out *specs_go.LinuxRdma) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "hcaHandles": - if in.IsNull() { - in.Skip() - out.HcaHandles = nil - } else { - if out.HcaHandles == nil { - out.HcaHandles = new(uint32) - } - *out.HcaHandles = uint32(in.Uint32()) - } - case "hcaObjects": - if in.IsNull() { - in.Skip() - out.HcaObjects = nil - } else { - if out.HcaObjects == nil { - out.HcaObjects = new(uint32) - } - *out.HcaObjects = uint32(in.Uint32()) - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo38(out *jwriter.Writer, in specs_go.LinuxRdma) { - out.RawByte('{') - first := true - _ = first - if in.HcaHandles != nil { - const prefix string = ",\"hcaHandles\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint32(uint32(*in.HcaHandles)) - } - if in.HcaObjects != nil { - const prefix string = ",\"hcaObjects\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint32(uint32(*in.HcaObjects)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo37(in *jlexer.Lexer, out *specs_go.LinuxNetwork) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "classID": - if in.IsNull() { - in.Skip() - out.ClassID = nil - } else { - if out.ClassID == nil { - out.ClassID = new(uint32) - } - *out.ClassID = uint32(in.Uint32()) - } - case "priorities": - if in.IsNull() { - in.Skip() - out.Priorities = nil - } else { - in.Delim('[') - if out.Priorities == nil { - if !in.IsDelim(']') { - out.Priorities = make([]specs_go.LinuxInterfacePriority, 0, 2) - } else { - out.Priorities = []specs_go.LinuxInterfacePriority{} - } - } else { - out.Priorities = (out.Priorities)[:0] - } - for !in.IsDelim(']') { - var v153 specs_go.LinuxInterfacePriority - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo39(in, &v153) - out.Priorities = append(out.Priorities, v153) - in.WantComma() - } - in.Delim(']') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo37(out *jwriter.Writer, in specs_go.LinuxNetwork) { - out.RawByte('{') - first := true - _ = first - if in.ClassID != nil { - const prefix string = ",\"classID\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint32(uint32(*in.ClassID)) - } - if len(in.Priorities) != 0 { - const prefix string = ",\"priorities\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v154, v155 := range in.Priorities { - if v154 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo39(out, v155) - } - out.RawByte(']') - } - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo39(in *jlexer.Lexer, out *specs_go.LinuxInterfacePriority) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "name": - out.Name = string(in.String()) - case "priority": - out.Priority = uint32(in.Uint32()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo39(out *jwriter.Writer, in specs_go.LinuxInterfacePriority) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"name\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Name)) - } - { - const prefix string = ",\"priority\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint32(uint32(in.Priority)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo36(in *jlexer.Lexer, out *specs_go.LinuxHugepageLimit) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "pageSize": - out.Pagesize = string(in.String()) - case "limit": - out.Limit = uint64(in.Uint64()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo36(out *jwriter.Writer, in specs_go.LinuxHugepageLimit) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"pageSize\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Pagesize)) - } - { - const prefix string = ",\"limit\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(in.Limit)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo35(in *jlexer.Lexer, out *specs_go.LinuxBlockIO) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "weight": - if in.IsNull() { - in.Skip() - out.Weight = nil - } else { - if out.Weight == nil { - out.Weight = new(uint16) - } - *out.Weight = uint16(in.Uint16()) - } - case "leafWeight": - if in.IsNull() { - in.Skip() - out.LeafWeight = nil - } else { - if out.LeafWeight == nil { - out.LeafWeight = new(uint16) - } - *out.LeafWeight = uint16(in.Uint16()) - } - case "weightDevice": - if in.IsNull() { - in.Skip() - out.WeightDevice = nil - } else { - in.Delim('[') - if out.WeightDevice == nil { - if !in.IsDelim(']') { - out.WeightDevice = make([]specs_go.LinuxWeightDevice, 0, 2) - } else { - out.WeightDevice = []specs_go.LinuxWeightDevice{} - } - } else { - out.WeightDevice = (out.WeightDevice)[:0] - } - for !in.IsDelim(']') { - var v156 specs_go.LinuxWeightDevice - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo40(in, &v156) - out.WeightDevice = append(out.WeightDevice, v156) - in.WantComma() - } - in.Delim(']') - } - case "throttleReadBpsDevice": - if in.IsNull() { - in.Skip() - out.ThrottleReadBpsDevice = nil - } else { - in.Delim('[') - if out.ThrottleReadBpsDevice == nil { - if !in.IsDelim(']') { - out.ThrottleReadBpsDevice = make([]specs_go.LinuxThrottleDevice, 0, 2) - } else { - out.ThrottleReadBpsDevice = []specs_go.LinuxThrottleDevice{} - } - } else { - out.ThrottleReadBpsDevice = (out.ThrottleReadBpsDevice)[:0] - } - for !in.IsDelim(']') { - var v157 specs_go.LinuxThrottleDevice - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo41(in, &v157) - out.ThrottleReadBpsDevice = append(out.ThrottleReadBpsDevice, v157) - in.WantComma() - } - in.Delim(']') - } - case "throttleWriteBpsDevice": - if in.IsNull() { - in.Skip() - out.ThrottleWriteBpsDevice = nil - } else { - in.Delim('[') - if out.ThrottleWriteBpsDevice == nil { - if !in.IsDelim(']') { - out.ThrottleWriteBpsDevice = make([]specs_go.LinuxThrottleDevice, 0, 2) - } else { - out.ThrottleWriteBpsDevice = []specs_go.LinuxThrottleDevice{} - } - } else { - out.ThrottleWriteBpsDevice = (out.ThrottleWriteBpsDevice)[:0] - } - for !in.IsDelim(']') { - var v158 specs_go.LinuxThrottleDevice - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo41(in, &v158) - out.ThrottleWriteBpsDevice = append(out.ThrottleWriteBpsDevice, v158) - in.WantComma() - } - in.Delim(']') - } - case "throttleReadIOPSDevice": - if in.IsNull() { - in.Skip() - out.ThrottleReadIOPSDevice = nil - } else { - in.Delim('[') - if out.ThrottleReadIOPSDevice == nil { - if !in.IsDelim(']') { - out.ThrottleReadIOPSDevice = make([]specs_go.LinuxThrottleDevice, 0, 2) - } else { - out.ThrottleReadIOPSDevice = []specs_go.LinuxThrottleDevice{} - } - } else { - out.ThrottleReadIOPSDevice = (out.ThrottleReadIOPSDevice)[:0] - } - for !in.IsDelim(']') { - var v159 specs_go.LinuxThrottleDevice - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo41(in, &v159) - out.ThrottleReadIOPSDevice = append(out.ThrottleReadIOPSDevice, v159) - in.WantComma() - } - in.Delim(']') - } - case "throttleWriteIOPSDevice": - if in.IsNull() { - in.Skip() - out.ThrottleWriteIOPSDevice = nil - } else { - in.Delim('[') - if out.ThrottleWriteIOPSDevice == nil { - if !in.IsDelim(']') { - out.ThrottleWriteIOPSDevice = make([]specs_go.LinuxThrottleDevice, 0, 2) - } else { - out.ThrottleWriteIOPSDevice = []specs_go.LinuxThrottleDevice{} - } - } else { - out.ThrottleWriteIOPSDevice = (out.ThrottleWriteIOPSDevice)[:0] - } - for !in.IsDelim(']') { - var v160 specs_go.LinuxThrottleDevice - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo41(in, &v160) - out.ThrottleWriteIOPSDevice = append(out.ThrottleWriteIOPSDevice, v160) - in.WantComma() - } - in.Delim(']') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo35(out *jwriter.Writer, in specs_go.LinuxBlockIO) { - out.RawByte('{') - first := true - _ = first - if in.Weight != nil { - const prefix string = ",\"weight\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint16(uint16(*in.Weight)) - } - if in.LeafWeight != nil { - const prefix string = ",\"leafWeight\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint16(uint16(*in.LeafWeight)) - } - if len(in.WeightDevice) != 0 { - const prefix string = ",\"weightDevice\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v161, v162 := range in.WeightDevice { - if v161 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo40(out, v162) - } - out.RawByte(']') - } - } - if len(in.ThrottleReadBpsDevice) != 0 { - const prefix string = ",\"throttleReadBpsDevice\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v163, v164 := range in.ThrottleReadBpsDevice { - if v163 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo41(out, v164) - } - out.RawByte(']') - } - } - if len(in.ThrottleWriteBpsDevice) != 0 { - const prefix string = ",\"throttleWriteBpsDevice\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v165, v166 := range in.ThrottleWriteBpsDevice { - if v165 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo41(out, v166) - } - out.RawByte(']') - } - } - if len(in.ThrottleReadIOPSDevice) != 0 { - const prefix string = ",\"throttleReadIOPSDevice\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v167, v168 := range in.ThrottleReadIOPSDevice { - if v167 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo41(out, v168) - } - out.RawByte(']') - } - } - if len(in.ThrottleWriteIOPSDevice) != 0 { - const prefix string = ",\"throttleWriteIOPSDevice\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v169, v170 := range in.ThrottleWriteIOPSDevice { - if v169 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo41(out, v170) - } - out.RawByte(']') - } - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo41(in *jlexer.Lexer, out *specs_go.LinuxThrottleDevice) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "rate": - out.Rate = uint64(in.Uint64()) - case "major": - out.Major = int64(in.Int64()) - case "minor": - out.Minor = int64(in.Int64()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo41(out *jwriter.Writer, in specs_go.LinuxThrottleDevice) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"rate\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(in.Rate)) - } - { - const prefix string = ",\"major\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(in.Major)) - } - { - const prefix string = ",\"minor\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(in.Minor)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo40(in *jlexer.Lexer, out *specs_go.LinuxWeightDevice) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "weight": - if in.IsNull() { - in.Skip() - out.Weight = nil - } else { - if out.Weight == nil { - out.Weight = new(uint16) - } - *out.Weight = uint16(in.Uint16()) - } - case "leafWeight": - if in.IsNull() { - in.Skip() - out.LeafWeight = nil - } else { - if out.LeafWeight == nil { - out.LeafWeight = new(uint16) - } - *out.LeafWeight = uint16(in.Uint16()) - } - case "major": - out.Major = int64(in.Int64()) - case "minor": - out.Minor = int64(in.Int64()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo40(out *jwriter.Writer, in specs_go.LinuxWeightDevice) { - out.RawByte('{') - first := true - _ = first - if in.Weight != nil { - const prefix string = ",\"weight\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint16(uint16(*in.Weight)) - } - if in.LeafWeight != nil { - const prefix string = ",\"leafWeight\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint16(uint16(*in.LeafWeight)) - } - { - const prefix string = ",\"major\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(in.Major)) - } - { - const prefix string = ",\"minor\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(in.Minor)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo34(in *jlexer.Lexer, out *specs_go.LinuxPids) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "limit": - out.Limit = int64(in.Int64()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo34(out *jwriter.Writer, in specs_go.LinuxPids) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"limit\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(in.Limit)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo33(in *jlexer.Lexer, out *specs_go.LinuxCPU) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "shares": - if in.IsNull() { - in.Skip() - out.Shares = nil - } else { - if out.Shares == nil { - out.Shares = new(uint64) - } - *out.Shares = uint64(in.Uint64()) - } - case "quota": - if in.IsNull() { - in.Skip() - out.Quota = nil - } else { - if out.Quota == nil { - out.Quota = new(int64) - } - *out.Quota = int64(in.Int64()) - } - case "period": - if in.IsNull() { - in.Skip() - out.Period = nil - } else { - if out.Period == nil { - out.Period = new(uint64) - } - *out.Period = uint64(in.Uint64()) - } - case "realtimeRuntime": - if in.IsNull() { - in.Skip() - out.RealtimeRuntime = nil - } else { - if out.RealtimeRuntime == nil { - out.RealtimeRuntime = new(int64) - } - *out.RealtimeRuntime = int64(in.Int64()) - } - case "realtimePeriod": - if in.IsNull() { - in.Skip() - out.RealtimePeriod = nil - } else { - if out.RealtimePeriod == nil { - out.RealtimePeriod = new(uint64) - } - *out.RealtimePeriod = uint64(in.Uint64()) - } - case "cpus": - out.Cpus = string(in.String()) - case "mems": - out.Mems = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo33(out *jwriter.Writer, in specs_go.LinuxCPU) { - out.RawByte('{') - first := true - _ = first - if in.Shares != nil { - const prefix string = ",\"shares\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(*in.Shares)) - } - if in.Quota != nil { - const prefix string = ",\"quota\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(*in.Quota)) - } - if in.Period != nil { - const prefix string = ",\"period\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(*in.Period)) - } - if in.RealtimeRuntime != nil { - const prefix string = ",\"realtimeRuntime\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(*in.RealtimeRuntime)) - } - if in.RealtimePeriod != nil { - const prefix string = ",\"realtimePeriod\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(*in.RealtimePeriod)) - } - if in.Cpus != "" { - const prefix string = ",\"cpus\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Cpus)) - } - if in.Mems != "" { - const prefix string = ",\"mems\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Mems)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo32(in *jlexer.Lexer, out *specs_go.LinuxMemory) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "limit": - if in.IsNull() { - in.Skip() - out.Limit = nil - } else { - if out.Limit == nil { - out.Limit = new(int64) - } - *out.Limit = int64(in.Int64()) - } - case "reservation": - if in.IsNull() { - in.Skip() - out.Reservation = nil - } else { - if out.Reservation == nil { - out.Reservation = new(int64) - } - *out.Reservation = int64(in.Int64()) - } - case "swap": - if in.IsNull() { - in.Skip() - out.Swap = nil - } else { - if out.Swap == nil { - out.Swap = new(int64) - } - *out.Swap = int64(in.Int64()) - } - case "kernel": - if in.IsNull() { - in.Skip() - out.Kernel = nil - } else { - if out.Kernel == nil { - out.Kernel = new(int64) - } - *out.Kernel = int64(in.Int64()) - } - case "kernelTCP": - if in.IsNull() { - in.Skip() - out.KernelTCP = nil - } else { - if out.KernelTCP == nil { - out.KernelTCP = new(int64) - } - *out.KernelTCP = int64(in.Int64()) - } - case "swappiness": - if in.IsNull() { - in.Skip() - out.Swappiness = nil - } else { - if out.Swappiness == nil { - out.Swappiness = new(uint64) - } - *out.Swappiness = uint64(in.Uint64()) - } - case "disableOOMKiller": - if in.IsNull() { - in.Skip() - out.DisableOOMKiller = nil - } else { - if out.DisableOOMKiller == nil { - out.DisableOOMKiller = new(bool) - } - *out.DisableOOMKiller = bool(in.Bool()) - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo32(out *jwriter.Writer, in specs_go.LinuxMemory) { - out.RawByte('{') - first := true - _ = first - if in.Limit != nil { - const prefix string = ",\"limit\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(*in.Limit)) - } - if in.Reservation != nil { - const prefix string = ",\"reservation\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(*in.Reservation)) - } - if in.Swap != nil { - const prefix string = ",\"swap\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(*in.Swap)) - } - if in.Kernel != nil { - const prefix string = ",\"kernel\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(*in.Kernel)) - } - if in.KernelTCP != nil { - const prefix string = ",\"kernelTCP\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(*in.KernelTCP)) - } - if in.Swappiness != nil { - const prefix string = ",\"swappiness\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(*in.Swappiness)) - } - if in.DisableOOMKiller != nil { - const prefix string = ",\"disableOOMKiller\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(*in.DisableOOMKiller)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo31(in *jlexer.Lexer, out *specs_go.LinuxDeviceCgroup) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "allow": - out.Allow = bool(in.Bool()) - case "type": - out.Type = string(in.String()) - case "major": - if in.IsNull() { - in.Skip() - out.Major = nil - } else { - if out.Major == nil { - out.Major = new(int64) - } - *out.Major = int64(in.Int64()) - } - case "minor": - if in.IsNull() { - in.Skip() - out.Minor = nil - } else { - if out.Minor == nil { - out.Minor = new(int64) - } - *out.Minor = int64(in.Int64()) - } - case "access": - out.Access = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo31(out *jwriter.Writer, in specs_go.LinuxDeviceCgroup) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"allow\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.Allow)) - } - if in.Type != "" { - const prefix string = ",\"type\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Type)) - } - if in.Major != nil { - const prefix string = ",\"major\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(*in.Major)) - } - if in.Minor != nil { - const prefix string = ",\"minor\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int64(int64(*in.Minor)) - } - if in.Access != "" { - const prefix string = ",\"access\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Access)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo23(in *jlexer.Lexer, out *specs_go.LinuxIDMapping) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "containerID": - out.ContainerID = uint32(in.Uint32()) - case "hostID": - out.HostID = uint32(in.Uint32()) - case "size": - out.Size = uint32(in.Uint32()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo23(out *jwriter.Writer, in specs_go.LinuxIDMapping) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"containerID\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint32(uint32(in.ContainerID)) - } - { - const prefix string = ",\"hostID\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint32(uint32(in.HostID)) - } - { - const prefix string = ",\"size\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint32(uint32(in.Size)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo5(in *jlexer.Lexer, out *specs_go.Hooks) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "prestart": - if in.IsNull() { - in.Skip() - out.Prestart = nil - } else { - in.Delim('[') - if out.Prestart == nil { - if !in.IsDelim(']') { - out.Prestart = make([]specs_go.Hook, 0, 1) - } else { - out.Prestart = []specs_go.Hook{} - } - } else { - out.Prestart = (out.Prestart)[:0] - } - for !in.IsDelim(']') { - var v171 specs_go.Hook - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo(in, &v171) - out.Prestart = append(out.Prestart, v171) - in.WantComma() - } - in.Delim(']') - } - case "poststart": - if in.IsNull() { - in.Skip() - out.Poststart = nil - } else { - in.Delim('[') - if out.Poststart == nil { - if !in.IsDelim(']') { - out.Poststart = make([]specs_go.Hook, 0, 1) - } else { - out.Poststart = []specs_go.Hook{} - } - } else { - out.Poststart = (out.Poststart)[:0] - } - for !in.IsDelim(']') { - var v172 specs_go.Hook - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo(in, &v172) - out.Poststart = append(out.Poststart, v172) - in.WantComma() - } - in.Delim(']') - } - case "poststop": - if in.IsNull() { - in.Skip() - out.Poststop = nil - } else { - in.Delim('[') - if out.Poststop == nil { - if !in.IsDelim(']') { - out.Poststop = make([]specs_go.Hook, 0, 1) - } else { - out.Poststop = []specs_go.Hook{} - } - } else { - out.Poststop = (out.Poststop)[:0] - } - for !in.IsDelim(']') { - var v173 specs_go.Hook - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo(in, &v173) - out.Poststop = append(out.Poststop, v173) - in.WantComma() - } - in.Delim(']') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo5(out *jwriter.Writer, in specs_go.Hooks) { - out.RawByte('{') - first := true - _ = first - if len(in.Prestart) != 0 { - const prefix string = ",\"prestart\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v174, v175 := range in.Prestart { - if v174 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo(out, v175) - } - out.RawByte(']') - } - } - if len(in.Poststart) != 0 { - const prefix string = ",\"poststart\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v176, v177 := range in.Poststart { - if v176 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo(out, v177) - } - out.RawByte(']') - } - } - if len(in.Poststop) != 0 { - const prefix string = ",\"poststop\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v178, v179 := range in.Poststop { - if v178 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo(out, v179) - } - out.RawByte(']') - } - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo4(in *jlexer.Lexer, out *specs_go.Mount) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "destination": - out.Destination = string(in.String()) - case "type": - out.Type = string(in.String()) - case "source": - out.Source = string(in.String()) - case "options": - if in.IsNull() { - in.Skip() - out.Options = nil - } else { - in.Delim('[') - if out.Options == nil { - if !in.IsDelim(']') { - out.Options = make([]string, 0, 4) - } else { - out.Options = []string{} - } - } else { - out.Options = (out.Options)[:0] - } - for !in.IsDelim(']') { - var v180 string - v180 = string(in.String()) - out.Options = append(out.Options, v180) - in.WantComma() - } - in.Delim(']') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo4(out *jwriter.Writer, in specs_go.Mount) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"destination\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Destination)) - } - if in.Type != "" { - const prefix string = ",\"type\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Type)) - } - if in.Source != "" { - const prefix string = ",\"source\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Source)) - } - if len(in.Options) != 0 { - const prefix string = ",\"options\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v181, v182 := range in.Options { - if v181 > 0 { - out.RawByte(',') - } - out.String(string(v182)) - } - out.RawByte(']') - } - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo3(in *jlexer.Lexer, out *specs_go.Root) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "path": - out.Path = string(in.String()) - case "readonly": - out.Readonly = bool(in.Bool()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo3(out *jwriter.Writer, in specs_go.Root) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"path\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Path)) - } - if in.Readonly { - const prefix string = ",\"readonly\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.Readonly)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo2(in *jlexer.Lexer, out *specs_go.Process) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "terminal": - out.Terminal = bool(in.Bool()) - case "consoleSize": - if in.IsNull() { - in.Skip() - out.ConsoleSize = nil - } else { - if out.ConsoleSize == nil { - out.ConsoleSize = new(specs_go.Box) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo42(in, &*out.ConsoleSize) - } - case "user": - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo43(in, &out.User) - case "args": - if in.IsNull() { - in.Skip() - out.Args = nil - } else { - in.Delim('[') - if out.Args == nil { - if !in.IsDelim(']') { - out.Args = make([]string, 0, 4) - } else { - out.Args = []string{} - } - } else { - out.Args = (out.Args)[:0] - } - for !in.IsDelim(']') { - var v183 string - v183 = string(in.String()) - out.Args = append(out.Args, v183) - in.WantComma() - } - in.Delim(']') - } - case "env": - if in.IsNull() { - in.Skip() - out.Env = nil - } else { - in.Delim('[') - if out.Env == nil { - if !in.IsDelim(']') { - out.Env = make([]string, 0, 4) - } else { - out.Env = []string{} - } - } else { - out.Env = (out.Env)[:0] - } - for !in.IsDelim(']') { - var v184 string - v184 = string(in.String()) - out.Env = append(out.Env, v184) - in.WantComma() - } - in.Delim(']') - } - case "cwd": - out.Cwd = string(in.String()) - case "capabilities": - if in.IsNull() { - in.Skip() - out.Capabilities = nil - } else { - if out.Capabilities == nil { - out.Capabilities = new(specs_go.LinuxCapabilities) - } - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo44(in, &*out.Capabilities) - } - case "rlimits": - if in.IsNull() { - in.Skip() - out.Rlimits = nil - } else { - in.Delim('[') - if out.Rlimits == nil { - if !in.IsDelim(']') { - out.Rlimits = make([]specs_go.POSIXRlimit, 0, 2) - } else { - out.Rlimits = []specs_go.POSIXRlimit{} - } - } else { - out.Rlimits = (out.Rlimits)[:0] - } - for !in.IsDelim(']') { - var v185 specs_go.POSIXRlimit - easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo45(in, &v185) - out.Rlimits = append(out.Rlimits, v185) - in.WantComma() - } - in.Delim(']') - } - case "noNewPrivileges": - out.NoNewPrivileges = bool(in.Bool()) - case "apparmorProfile": - out.ApparmorProfile = string(in.String()) - case "oomScoreAdj": - if in.IsNull() { - in.Skip() - out.OOMScoreAdj = nil - } else { - if out.OOMScoreAdj == nil { - out.OOMScoreAdj = new(int) - } - *out.OOMScoreAdj = int(in.Int()) - } - case "selinuxLabel": - out.SelinuxLabel = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo2(out *jwriter.Writer, in specs_go.Process) { - out.RawByte('{') - first := true - _ = first - if in.Terminal { - const prefix string = ",\"terminal\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.Terminal)) - } - if in.ConsoleSize != nil { - const prefix string = ",\"consoleSize\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo42(out, *in.ConsoleSize) - } - { - const prefix string = ",\"user\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo43(out, in.User) - } - { - const prefix string = ",\"args\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.Args == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { - out.RawString("null") - } else { - out.RawByte('[') - for v186, v187 := range in.Args { - if v186 > 0 { - out.RawByte(',') - } - out.String(string(v187)) - } - out.RawByte(']') - } - } - if len(in.Env) != 0 { - const prefix string = ",\"env\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v188, v189 := range in.Env { - if v188 > 0 { - out.RawByte(',') - } - out.String(string(v189)) - } - out.RawByte(']') - } - } - { - const prefix string = ",\"cwd\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Cwd)) - } - if in.Capabilities != nil { - const prefix string = ",\"capabilities\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo44(out, *in.Capabilities) - } - if len(in.Rlimits) != 0 { - const prefix string = ",\"rlimits\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v190, v191 := range in.Rlimits { - if v190 > 0 { - out.RawByte(',') - } - easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo45(out, v191) - } - out.RawByte(']') - } - } - if in.NoNewPrivileges { - const prefix string = ",\"noNewPrivileges\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.NoNewPrivileges)) - } - if in.ApparmorProfile != "" { - const prefix string = ",\"apparmorProfile\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.ApparmorProfile)) - } - if in.OOMScoreAdj != nil { - const prefix string = ",\"oomScoreAdj\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int(int(*in.OOMScoreAdj)) - } - if in.SelinuxLabel != "" { - const prefix string = ",\"selinuxLabel\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.SelinuxLabel)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo45(in *jlexer.Lexer, out *specs_go.POSIXRlimit) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "type": - out.Type = string(in.String()) - case "hard": - out.Hard = uint64(in.Uint64()) - case "soft": - out.Soft = uint64(in.Uint64()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo45(out *jwriter.Writer, in specs_go.POSIXRlimit) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"type\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Type)) - } - { - const prefix string = ",\"hard\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(in.Hard)) - } - { - const prefix string = ",\"soft\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint64(uint64(in.Soft)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo44(in *jlexer.Lexer, out *specs_go.LinuxCapabilities) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "bounding": - if in.IsNull() { - in.Skip() - out.Bounding = nil - } else { - in.Delim('[') - if out.Bounding == nil { - if !in.IsDelim(']') { - out.Bounding = make([]string, 0, 4) - } else { - out.Bounding = []string{} - } - } else { - out.Bounding = (out.Bounding)[:0] - } - for !in.IsDelim(']') { - var v192 string - v192 = string(in.String()) - out.Bounding = append(out.Bounding, v192) - in.WantComma() - } - in.Delim(']') - } - case "effective": - if in.IsNull() { - in.Skip() - out.Effective = nil - } else { - in.Delim('[') - if out.Effective == nil { - if !in.IsDelim(']') { - out.Effective = make([]string, 0, 4) - } else { - out.Effective = []string{} - } - } else { - out.Effective = (out.Effective)[:0] - } - for !in.IsDelim(']') { - var v193 string - v193 = string(in.String()) - out.Effective = append(out.Effective, v193) - in.WantComma() - } - in.Delim(']') - } - case "inheritable": - if in.IsNull() { - in.Skip() - out.Inheritable = nil - } else { - in.Delim('[') - if out.Inheritable == nil { - if !in.IsDelim(']') { - out.Inheritable = make([]string, 0, 4) - } else { - out.Inheritable = []string{} - } - } else { - out.Inheritable = (out.Inheritable)[:0] - } - for !in.IsDelim(']') { - var v194 string - v194 = string(in.String()) - out.Inheritable = append(out.Inheritable, v194) - in.WantComma() - } - in.Delim(']') - } - case "permitted": - if in.IsNull() { - in.Skip() - out.Permitted = nil - } else { - in.Delim('[') - if out.Permitted == nil { - if !in.IsDelim(']') { - out.Permitted = make([]string, 0, 4) - } else { - out.Permitted = []string{} - } - } else { - out.Permitted = (out.Permitted)[:0] - } - for !in.IsDelim(']') { - var v195 string - v195 = string(in.String()) - out.Permitted = append(out.Permitted, v195) - in.WantComma() - } - in.Delim(']') - } - case "ambient": - if in.IsNull() { - in.Skip() - out.Ambient = nil - } else { - in.Delim('[') - if out.Ambient == nil { - if !in.IsDelim(']') { - out.Ambient = make([]string, 0, 4) - } else { - out.Ambient = []string{} - } - } else { - out.Ambient = (out.Ambient)[:0] - } - for !in.IsDelim(']') { - var v196 string - v196 = string(in.String()) - out.Ambient = append(out.Ambient, v196) - in.WantComma() - } - in.Delim(']') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo44(out *jwriter.Writer, in specs_go.LinuxCapabilities) { - out.RawByte('{') - first := true - _ = first - if len(in.Bounding) != 0 { - const prefix string = ",\"bounding\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v197, v198 := range in.Bounding { - if v197 > 0 { - out.RawByte(',') - } - out.String(string(v198)) - } - out.RawByte(']') - } - } - if len(in.Effective) != 0 { - const prefix string = ",\"effective\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v199, v200 := range in.Effective { - if v199 > 0 { - out.RawByte(',') - } - out.String(string(v200)) - } - out.RawByte(']') - } - } - if len(in.Inheritable) != 0 { - const prefix string = ",\"inheritable\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v201, v202 := range in.Inheritable { - if v201 > 0 { - out.RawByte(',') - } - out.String(string(v202)) - } - out.RawByte(']') - } - } - if len(in.Permitted) != 0 { - const prefix string = ",\"permitted\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v203, v204 := range in.Permitted { - if v203 > 0 { - out.RawByte(',') - } - out.String(string(v204)) - } - out.RawByte(']') - } - } - if len(in.Ambient) != 0 { - const prefix string = ",\"ambient\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v205, v206 := range in.Ambient { - if v205 > 0 { - out.RawByte(',') - } - out.String(string(v206)) - } - out.RawByte(']') - } - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo43(in *jlexer.Lexer, out *specs_go.User) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "uid": - out.UID = uint32(in.Uint32()) - case "gid": - out.GID = uint32(in.Uint32()) - case "additionalGids": - if in.IsNull() { - in.Skip() - out.AdditionalGids = nil - } else { - in.Delim('[') - if out.AdditionalGids == nil { - if !in.IsDelim(']') { - out.AdditionalGids = make([]uint32, 0, 16) - } else { - out.AdditionalGids = []uint32{} - } - } else { - out.AdditionalGids = (out.AdditionalGids)[:0] - } - for !in.IsDelim(']') { - var v207 uint32 - v207 = uint32(in.Uint32()) - out.AdditionalGids = append(out.AdditionalGids, v207) - in.WantComma() - } - in.Delim(']') - } - case "username": - out.Username = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo43(out *jwriter.Writer, in specs_go.User) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"uid\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint32(uint32(in.UID)) - } - { - const prefix string = ",\"gid\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint32(uint32(in.GID)) - } - if len(in.AdditionalGids) != 0 { - const prefix string = ",\"additionalGids\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - { - out.RawByte('[') - for v208, v209 := range in.AdditionalGids { - if v208 > 0 { - out.RawByte(',') - } - out.Uint32(uint32(v209)) - } - out.RawByte(']') - } - } - if in.Username != "" { - const prefix string = ",\"username\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Username)) - } - out.RawByte('}') -} -func easyjson1dbef17bDecodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo42(in *jlexer.Lexer, out *specs_go.Box) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "height": - out.Height = uint(in.Uint()) - case "width": - out.Width = uint(in.Uint()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjson1dbef17bEncodeGithubComContainersLibpodVendorGithubComOpencontainersRuntimeSpecSpecsGo42(out *jwriter.Writer, in specs_go.Box) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"height\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint(uint(in.Height)) - } - { - const prefix string = ",\"width\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Uint(uint(in.Width)) - } - out.RawByte('}') -} diff --git a/libpod/container_graph_test.go b/libpod/container_graph_test.go index 25461f1f4..d1a52658d 100644 --- a/libpod/container_graph_test.go +++ b/libpod/container_graph_test.go @@ -1,10 +1,9 @@ package libpod import ( - "io/ioutil" - "os" "testing" + "github.com/containers/libpod/libpod/lock" "github.com/stretchr/testify/assert" ) @@ -17,11 +16,12 @@ func TestBuildContainerGraphNoCtrsIsEmpty(t *testing.T) { } func TestBuildContainerGraphOneCtr(t *testing.T) { - tmpDir, err := ioutil.TempDir("", tmpDirPrefix) - assert.NoError(t, err) - defer os.RemoveAll(tmpDir) + manager, err := lock.NewInMemoryManager(16) + if err != nil { + t.Fatalf("Error setting up locks: %v", err) + } - ctr1, err := getTestCtr1(tmpDir) + ctr1, err := getTestCtr1(manager) assert.NoError(t, err) graph, err := buildContainerGraph([]*Container{ctr1}) @@ -39,13 +39,14 @@ func TestBuildContainerGraphOneCtr(t *testing.T) { } func TestBuildContainerGraphTwoCtrNoEdge(t *testing.T) { - tmpDir, err := ioutil.TempDir("", tmpDirPrefix) - assert.NoError(t, err) - defer os.RemoveAll(tmpDir) + manager, err := lock.NewInMemoryManager(16) + if err != nil { + t.Fatalf("Error setting up locks: %v", err) + } - ctr1, err := getTestCtr1(tmpDir) + ctr1, err := getTestCtr1(manager) assert.NoError(t, err) - ctr2, err := getTestCtr2(tmpDir) + ctr2, err := getTestCtr2(manager) assert.NoError(t, err) graph, err := buildContainerGraph([]*Container{ctr1, ctr2}) @@ -64,13 +65,14 @@ func TestBuildContainerGraphTwoCtrNoEdge(t *testing.T) { } func TestBuildContainerGraphTwoCtrOneEdge(t *testing.T) { - tmpDir, err := ioutil.TempDir("", tmpDirPrefix) - assert.NoError(t, err) - defer os.RemoveAll(tmpDir) + manager, err := lock.NewInMemoryManager(16) + if err != nil { + t.Fatalf("Error setting up locks: %v", err) + } - ctr1, err := getTestCtr1(tmpDir) + ctr1, err := getTestCtr1(manager) assert.NoError(t, err) - ctr2, err := getTestCtr2(tmpDir) + ctr2, err := getTestCtr2(manager) assert.NoError(t, err) ctr2.config.UserNsCtr = ctr1.config.ID @@ -85,13 +87,14 @@ func TestBuildContainerGraphTwoCtrOneEdge(t *testing.T) { } func TestBuildContainerGraphTwoCtrCycle(t *testing.T) { - tmpDir, err := ioutil.TempDir("", tmpDirPrefix) - assert.NoError(t, err) - defer os.RemoveAll(tmpDir) + manager, err := lock.NewInMemoryManager(16) + if err != nil { + t.Fatalf("Error setting up locks: %v", err) + } - ctr1, err := getTestCtr1(tmpDir) + ctr1, err := getTestCtr1(manager) assert.NoError(t, err) - ctr2, err := getTestCtr2(tmpDir) + ctr2, err := getTestCtr2(manager) assert.NoError(t, err) ctr2.config.UserNsCtr = ctr1.config.ID ctr1.config.NetNsCtr = ctr2.config.ID @@ -101,15 +104,16 @@ func TestBuildContainerGraphTwoCtrCycle(t *testing.T) { } func TestBuildContainerGraphThreeCtrNoEdges(t *testing.T) { - tmpDir, err := ioutil.TempDir("", tmpDirPrefix) - assert.NoError(t, err) - defer os.RemoveAll(tmpDir) + manager, err := lock.NewInMemoryManager(16) + if err != nil { + t.Fatalf("Error setting up locks: %v", err) + } - ctr1, err := getTestCtr1(tmpDir) + ctr1, err := getTestCtr1(manager) assert.NoError(t, err) - ctr2, err := getTestCtr2(tmpDir) + ctr2, err := getTestCtr2(manager) assert.NoError(t, err) - ctr3, err := getTestCtrN("3", tmpDir) + ctr3, err := getTestCtrN("3", manager) assert.NoError(t, err) graph, err := buildContainerGraph([]*Container{ctr1, ctr2, ctr3}) @@ -132,15 +136,16 @@ func TestBuildContainerGraphThreeCtrNoEdges(t *testing.T) { } func TestBuildContainerGraphThreeContainersTwoInCycle(t *testing.T) { - tmpDir, err := ioutil.TempDir("", tmpDirPrefix) - assert.NoError(t, err) - defer os.RemoveAll(tmpDir) + manager, err := lock.NewInMemoryManager(16) + if err != nil { + t.Fatalf("Error setting up locks: %v", err) + } - ctr1, err := getTestCtr1(tmpDir) + ctr1, err := getTestCtr1(manager) assert.NoError(t, err) - ctr2, err := getTestCtr2(tmpDir) + ctr2, err := getTestCtr2(manager) assert.NoError(t, err) - ctr3, err := getTestCtrN("3", tmpDir) + ctr3, err := getTestCtrN("3", manager) assert.NoError(t, err) ctr1.config.UserNsCtr = ctr2.config.ID ctr2.config.IPCNsCtr = ctr1.config.ID @@ -150,15 +155,16 @@ func TestBuildContainerGraphThreeContainersTwoInCycle(t *testing.T) { } func TestBuildContainerGraphThreeContainersCycle(t *testing.T) { - tmpDir, err := ioutil.TempDir("", tmpDirPrefix) - assert.NoError(t, err) - defer os.RemoveAll(tmpDir) + manager, err := lock.NewInMemoryManager(16) + if err != nil { + t.Fatalf("Error setting up locks: %v", err) + } - ctr1, err := getTestCtr1(tmpDir) + ctr1, err := getTestCtr1(manager) assert.NoError(t, err) - ctr2, err := getTestCtr2(tmpDir) + ctr2, err := getTestCtr2(manager) assert.NoError(t, err) - ctr3, err := getTestCtrN("3", tmpDir) + ctr3, err := getTestCtrN("3", manager) assert.NoError(t, err) ctr1.config.UserNsCtr = ctr2.config.ID ctr2.config.IPCNsCtr = ctr3.config.ID @@ -169,15 +175,16 @@ func TestBuildContainerGraphThreeContainersCycle(t *testing.T) { } func TestBuildContainerGraphThreeContainersNoCycle(t *testing.T) { - tmpDir, err := ioutil.TempDir("", tmpDirPrefix) - assert.NoError(t, err) - defer os.RemoveAll(tmpDir) + manager, err := lock.NewInMemoryManager(16) + if err != nil { + t.Fatalf("Error setting up locks: %v", err) + } - ctr1, err := getTestCtr1(tmpDir) + ctr1, err := getTestCtr1(manager) assert.NoError(t, err) - ctr2, err := getTestCtr2(tmpDir) + ctr2, err := getTestCtr2(manager) assert.NoError(t, err) - ctr3, err := getTestCtrN("3", tmpDir) + ctr3, err := getTestCtrN("3", manager) assert.NoError(t, err) ctr1.config.UserNsCtr = ctr2.config.ID ctr1.config.NetNsCtr = ctr3.config.ID @@ -194,17 +201,18 @@ func TestBuildContainerGraphThreeContainersNoCycle(t *testing.T) { } func TestBuildContainerGraphFourContainersNoEdges(t *testing.T) { - tmpDir, err := ioutil.TempDir("", tmpDirPrefix) - assert.NoError(t, err) - defer os.RemoveAll(tmpDir) + manager, err := lock.NewInMemoryManager(16) + if err != nil { + t.Fatalf("Error setting up locks: %v", err) + } - ctr1, err := getTestCtr1(tmpDir) + ctr1, err := getTestCtr1(manager) assert.NoError(t, err) - ctr2, err := getTestCtr2(tmpDir) + ctr2, err := getTestCtr2(manager) assert.NoError(t, err) - ctr3, err := getTestCtrN("3", tmpDir) + ctr3, err := getTestCtrN("3", manager) assert.NoError(t, err) - ctr4, err := getTestCtrN("4", tmpDir) + ctr4, err := getTestCtrN("4", manager) assert.NoError(t, err) graph, err := buildContainerGraph([]*Container{ctr1, ctr2, ctr3, ctr4}) @@ -231,18 +239,20 @@ func TestBuildContainerGraphFourContainersNoEdges(t *testing.T) { } func TestBuildContainerGraphFourContainersTwoInCycle(t *testing.T) { - tmpDir, err := ioutil.TempDir("", tmpDirPrefix) - assert.NoError(t, err) - defer os.RemoveAll(tmpDir) + manager, err := lock.NewInMemoryManager(16) + if err != nil { + t.Fatalf("Error setting up locks: %v", err) + } - ctr1, err := getTestCtr1(tmpDir) + ctr1, err := getTestCtr1(manager) assert.NoError(t, err) - ctr2, err := getTestCtr2(tmpDir) + ctr2, err := getTestCtr2(manager) assert.NoError(t, err) - ctr3, err := getTestCtrN("3", tmpDir) + ctr3, err := getTestCtrN("3", manager) assert.NoError(t, err) - ctr4, err := getTestCtrN("4", tmpDir) + ctr4, err := getTestCtrN("4", manager) assert.NoError(t, err) + ctr1.config.IPCNsCtr = ctr2.config.ID ctr2.config.UserNsCtr = ctr1.config.ID @@ -251,18 +261,20 @@ func TestBuildContainerGraphFourContainersTwoInCycle(t *testing.T) { } func TestBuildContainerGraphFourContainersAllInCycle(t *testing.T) { - tmpDir, err := ioutil.TempDir("", tmpDirPrefix) - assert.NoError(t, err) - defer os.RemoveAll(tmpDir) + manager, err := lock.NewInMemoryManager(16) + if err != nil { + t.Fatalf("Error setting up locks: %v", err) + } - ctr1, err := getTestCtr1(tmpDir) + ctr1, err := getTestCtr1(manager) assert.NoError(t, err) - ctr2, err := getTestCtr2(tmpDir) + ctr2, err := getTestCtr2(manager) assert.NoError(t, err) - ctr3, err := getTestCtrN("3", tmpDir) + ctr3, err := getTestCtrN("3", manager) assert.NoError(t, err) - ctr4, err := getTestCtrN("4", tmpDir) + ctr4, err := getTestCtrN("4", manager) assert.NoError(t, err) + ctr1.config.IPCNsCtr = ctr2.config.ID ctr2.config.UserNsCtr = ctr3.config.ID ctr3.config.NetNsCtr = ctr4.config.ID @@ -273,18 +285,20 @@ func TestBuildContainerGraphFourContainersAllInCycle(t *testing.T) { } func TestBuildContainerGraphFourContainersNoneInCycle(t *testing.T) { - tmpDir, err := ioutil.TempDir("", tmpDirPrefix) - assert.NoError(t, err) - defer os.RemoveAll(tmpDir) + manager, err := lock.NewInMemoryManager(16) + if err != nil { + t.Fatalf("Error setting up locks: %v", err) + } - ctr1, err := getTestCtr1(tmpDir) + ctr1, err := getTestCtr1(manager) assert.NoError(t, err) - ctr2, err := getTestCtr2(tmpDir) + ctr2, err := getTestCtr2(manager) assert.NoError(t, err) - ctr3, err := getTestCtrN("3", tmpDir) + ctr3, err := getTestCtrN("3", manager) assert.NoError(t, err) - ctr4, err := getTestCtrN("4", tmpDir) + ctr4, err := getTestCtrN("4", manager) assert.NoError(t, err) + ctr1.config.IPCNsCtr = ctr2.config.ID ctr1.config.NetNsCtr = ctr3.config.ID ctr2.config.UserNsCtr = ctr3.config.ID diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 06a0c9f32..e2730c282 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -12,7 +12,10 @@ import ( func (c *Container) getContainerInspectData(size bool, driverData *inspect.Data) (*inspect.ContainerInspectData, error) { config := c.config runtimeInfo := c.state - spec := c.config.Spec + spec, err := c.specFromState() + if err != nil { + return nil, err + } // Process is allowed to be nil in the spec args := []string{} diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 928be52ae..39c1501da 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -3,7 +3,6 @@ package libpod import ( "bytes" "context" - "encoding/json" "fmt" "io" "io/ioutil" @@ -389,7 +388,7 @@ func (c *Container) teardownStorage() error { // Reset resets state fields to default values // It is performed before a refresh and clears the state after a reboot // It does not save the results - assumes the database will do that for us -func resetState(state *containerState) error { +func resetState(state *ContainerState) error { state.PID = 0 state.Mountpoint = "" state.Mounted = false @@ -401,7 +400,10 @@ func resetState(state *containerState) error { return nil } -// Refresh refreshes the container's state after a restart +// Refresh refreshes the container's state after a restart. +// Refresh cannot perform any operations that would lock another container. +// We cannot guarantee any other container has a valid lock at the time it is +// running. func (c *Container) refresh() error { // Don't need a full sync, but we do need to update from the database to // pick up potentially-missing container state @@ -447,6 +449,13 @@ func (c *Container) refresh() error { c.state.DestinationRunDir = filepath.Join(c.state.UserNSRoot, "rundir") } + // We need to pick up a new lock + lock, err := c.runtime.lockManager.RetrieveLock(c.config.LockID) + if err != nil { + return errors.Wrapf(err, "error acquiring lock for container %s", c.ID()) + } + c.lock = lock + if err := c.save(); err != nil { return errors.Wrapf(err, "error refreshing state for container %s", c.ID()) } @@ -531,7 +540,7 @@ func (c *Container) isStopped() (bool, error) { if err != nil { return true, err } - return (c.state.State == ContainerStateStopped || c.state.State == ContainerStateExited), nil + return (c.state.State != ContainerStateRunning && c.state.State != ContainerStatePaused), nil } // save container state to the database @@ -748,6 +757,10 @@ func (c *Container) initAndStart(ctx context.Context) (err error) { // Internal, non-locking function to start a container func (c *Container) start() error { + if c.config.Spec.Process != nil { + logrus.Debugf("Starting container %s with command %v", c.ID(), c.config.Spec.Process.Args) + } + if err := c.runtime.ociRuntime.startContainer(c); err != nil { return err } @@ -1167,6 +1180,7 @@ func (c *Container) saveSpec(spec *spec.Spec) error { return nil } +// Warning: precreate hooks may alter 'config' in place. func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (extensionStageHooks map[string][]spec.Hook, err error) { var locale string var ok bool @@ -1195,13 +1209,13 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (exten } } + allHooks := make(map[string][]spec.Hook) if c.runtime.config.HooksDir == nil { if rootless.IsRootless() { return nil, nil } - allHooks := make(map[string][]spec.Hook) for _, hDir := range []string{hooks.DefaultDir, hooks.OverrideDir} { - manager, err := hooks.New(ctx, []string{hDir}, []string{"poststop"}, lang) + manager, err := hooks.New(ctx, []string{hDir}, []string{"precreate", "poststop"}, lang) if err != nil { if os.IsNotExist(err) { continue @@ -1219,19 +1233,32 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (exten allHooks[i] = hook } } - return allHooks, nil + } else { + manager, err := hooks.New(ctx, c.runtime.config.HooksDir, []string{"precreate", "poststop"}, lang) + if err != nil { + if os.IsNotExist(err) { + logrus.Warnf("Requested OCI hooks directory %q does not exist", c.runtime.config.HooksDir) + return nil, nil + } + return nil, err + } + + allHooks, err = manager.Hooks(config, c.Spec().Annotations, len(c.config.UserVolumes) > 0) + if err != nil { + return nil, err + } } - manager, err := hooks.New(ctx, c.runtime.config.HooksDir, []string{"poststop"}, lang) + hookErr, err := exec.RuntimeConfigFilter(ctx, allHooks["precreate"], config, exec.DefaultPostKillTimeout) if err != nil { - if os.IsNotExist(err) { - logrus.Warnf("Requested OCI hooks directory %q does not exist", c.runtime.config.HooksDir) - return nil, nil + logrus.Warnf("container %s: precreate hook: %v", c.ID(), err) + if hookErr != nil && hookErr != err { + logrus.Debugf("container %s: precreate hook (hook error): %v", c.ID(), hookErr) } return nil, err } - return manager.Hooks(config, c.Spec().Annotations, len(c.config.UserVolumes) > 0) + return allHooks, nil } // mount mounts the container's root filesystem diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 0745b7732..bcdfdaee3 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -4,7 +4,6 @@ package libpod import ( "context" - "encoding/json" "fmt" "io/ioutil" "net" @@ -20,6 +19,7 @@ import ( cnitypes "github.com/containernetworking/cni/pkg/types/current" "github.com/containernetworking/plugins/pkg/ns" crioAnnotations "github.com/containers/libpod/pkg/annotations" + "github.com/containers/libpod/pkg/apparmor" "github.com/containers/libpod/pkg/criu" "github.com/containers/libpod/pkg/lookup" "github.com/containers/libpod/pkg/resolvconf" @@ -185,6 +185,13 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } } + // Apply AppArmor checks and load the default profile if needed. + updatedProfile, err := apparmor.CheckProfileAndLoadDefault(c.config.Spec.Process.ApparmorProfile) + if err != nil { + return nil, err + } + g.SetProcessApparmorProfile(updatedProfile) + if err := c.makeBindMounts(); err != nil { return nil, err } @@ -219,7 +226,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { Options: []string{"bind", "private"}, } if c.IsReadOnly() && dstPath != "/dev/shm" { - newMount.Options = append(newMount.Options, "ro") + newMount.Options = append(newMount.Options, "ro", "nosuid", "noexec", "nodev") } if !MountExists(g.Mounts(), dstPath) { g.AddMount(newMount) @@ -228,10 +235,6 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } } - if c.state.ExtensionStageHooks, err = c.setupOCIHooks(ctx, g.Config); err != nil { - return nil, errors.Wrapf(err, "error setting up OCI Hooks") - } - // Bind builtin image volumes if c.config.Rootfs == "" && c.config.ImageVolumes { if err := c.addLocalVolumes(ctx, &g, execUser); err != nil { @@ -384,6 +387,12 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { logrus.Debugf("set root propagation to %q", rootPropagation) g.SetLinuxRootPropagation(rootPropagation) } + + // Warning: precreate hooks may alter g.Config in place. + if c.state.ExtensionStageHooks, err = c.setupOCIHooks(ctx, g.Config); err != nil { + return nil, errors.Wrapf(err, "error setting up OCI Hooks") + } + return g.Config, nil } @@ -481,7 +490,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO // Save network.status. This is needed to restore the container with // the same IP. Currently limited to one IP address in a container // with one interface. - formatJSON, err := json.MarshalIndent(c.state.NetworkStatus, "", " ") + formatJSON, err := json.MarshalIndent(c.state.NetworkStatus, "", " ") if err != nil { return err } @@ -547,10 +556,8 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti } } if IP != nil { - env := fmt.Sprintf("IP=%s", IP) // Tell CNI which IP address we want. - os.Setenv("CNI_ARGS", env) - logrus.Debugf("Restoring container with %s", env) + c.requestedIP = IP } } @@ -566,12 +573,6 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti return err } - // TODO: use existing way to request static IPs, once it is merged in ocicni - // https://github.com/cri-o/ocicni/pull/23/ - - // CNI_ARGS was used to request a certain IP address. Unconditionally remove it. - os.Unsetenv("CNI_ARGS") - // Read config jsonPath := filepath.Join(c.bundlePath(), "config.json") logrus.Debugf("generate.NewFromFile at %v", jsonPath) diff --git a/libpod/container_internal_test.go b/libpod/container_internal_test.go index 51fb58713..f1e2b70a7 100644 --- a/libpod/container_internal_test.go +++ b/libpod/container_internal_test.go @@ -28,7 +28,7 @@ func TestPostDeleteHooks(t *testing.T) { statePath := filepath.Join(dir, "state") copyPath := filepath.Join(dir, "copy") c := Container{ - config: &Config{ + config: &ContainerConfig{ ID: "123abc", Spec: &rspec.Spec{ Annotations: map[string]string{ @@ -37,7 +37,7 @@ func TestPostDeleteHooks(t *testing.T) { }, StaticDir: dir, // not the bundle, but good enough for this test }, - state: &containerState{ + state: &ContainerState{ ExtensionStageHooks: map[string][]rspec.Hook{ "poststop": { rspec.Hook{ diff --git a/libpod/image/filters.go b/libpod/image/filters.go deleted file mode 100644 index d0c3adfb5..000000000 --- a/libpod/image/filters.go +++ /dev/null @@ -1,83 +0,0 @@ -package image - -import ( - "context" - "strings" - "time" - - "github.com/containers/libpod/pkg/inspect" -) - -// ResultFilter is a mock function for image filtering -type ResultFilter func(*Image) bool - -// Filter is a function to determine whether an image is included in -// command output. Images to be outputted are tested using the function. A true -// return will include the image, a false return will exclude it. -type Filter func(*Image, *inspect.ImageData) bool - -// CreatedBeforeFilter allows you to filter on images created before -// the given time.Time -func CreatedBeforeFilter(createTime time.Time) ResultFilter { - return func(i *Image) bool { - return i.Created().Before(createTime) - } -} - -// CreatedAfterFilter allows you to filter on images created after -// the given time.Time -func CreatedAfterFilter(createTime time.Time) ResultFilter { - return func(i *Image) bool { - return i.Created().After(createTime) - } -} - -// DanglingFilter allows you to filter images for dangling images -func DanglingFilter() ResultFilter { - return func(i *Image) bool { - return i.Dangling() - } -} - -// LabelFilter allows you to filter by images labels key and/or value -func LabelFilter(ctx context.Context, labelfilter string) ResultFilter { - // We need to handle both label=key and label=key=value - return func(i *Image) bool { - var value string - splitFilter := strings.Split(labelfilter, "=") - key := splitFilter[0] - if len(splitFilter) > 1 { - value = splitFilter[1] - } - labels, err := i.Labels(ctx) - if err != nil { - return false - } - if len(strings.TrimSpace(labels[key])) > 0 && len(strings.TrimSpace(value)) == 0 { - return true - } - return labels[key] == value - } -} - -// OutputImageFilter allows you to filter by an a specific image name -func OutputImageFilter(userImage *Image) ResultFilter { - return func(i *Image) bool { - return userImage.ID() == i.ID() - } -} - -// FilterImages filters images using a set of predefined filter funcs -func FilterImages(images []*Image, filters []ResultFilter) []*Image { - var filteredImages []*Image - for _, image := range images { - include := true - for _, filter := range filters { - include = include && filter(image) - } - if include { - filteredImages = append(filteredImages, image) - } - } - return filteredImages -} diff --git a/libpod/image/image.go b/libpod/image/image.go index 3a6d0e305..ea326d820 100644 --- a/libpod/image/image.go +++ b/libpod/image/image.go @@ -25,7 +25,7 @@ import ( "github.com/containers/libpod/pkg/util" "github.com/containers/storage" "github.com/containers/storage/pkg/reexec" - "github.com/opencontainers/go-digest" + digest "github.com/opencontainers/go-digest" ociv1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -226,7 +226,6 @@ func (i *Image) getLocalImage() (*storage.Image, error) { i.InputName = dest.DockerReference().String() } - var taggedName string img, err := i.imageruntime.getImage(stripSha256(i.InputName)) if err == nil { return img.image, err @@ -240,25 +239,18 @@ func (i *Image) getLocalImage() (*storage.Image, error) { return nil, err } - // the inputname isn't tagged, so we assume latest and try again - if !decomposedImage.isTagged { - taggedName = fmt.Sprintf("%s:latest", i.InputName) - img, err = i.imageruntime.getImage(taggedName) - if err == nil { - return img.image, nil - } - } - // The image has a registry name in it and we made sure we looked for it locally // with a tag. It cannot be local. if decomposedImage.hasRegistry { return nil, errors.Wrapf(ErrNoSuchImage, imageError) - } - // if the image is saved with the repository localhost, searching with localhost prepended is necessary // We don't need to strip the sha because we have already determined it is not an ID - img, err = i.imageruntime.getImage(fmt.Sprintf("%s/%s", DefaultLocalRegistry, i.InputName)) + ref, err := decomposedImage.referenceWithRegistry(DefaultLocalRegistry) + if err != nil { + return nil, err + } + img, err = i.imageruntime.getImage(ref.String()) if err == nil { return img.image, err } @@ -305,12 +297,24 @@ func (i *Image) Names() []string { } // RepoDigests returns a string array of repodigests associated with the image -func (i *Image) RepoDigests() []string { +func (i *Image) RepoDigests() ([]string, error) { var repoDigests []string + digest := i.Digest() + for _, name := range i.Names() { - repoDigests = append(repoDigests, strings.SplitN(name, ":", 2)[0]+"@"+i.Digest().String()) + named, err := reference.ParseNormalizedNamed(name) + if err != nil { + return nil, err + } + + canonical, err := reference.WithDigest(reference.TrimNamed(named), digest) + if err != nil { + return nil, err + } + + repoDigests = append(repoDigests, canonical.String()) } - return repoDigests + return repoDigests, nil } // Created returns the time the image was created @@ -440,35 +444,42 @@ func getImageDigest(ctx context.Context, src types.ImageReference, sc *types.Sys return "@" + digest.Hex(), nil } -// normalizeTag returns the canonical version of tag for use in Image.Names() -func normalizeTag(tag string) (string, error) { +// normalizedTag returns the canonical version of tag for use in Image.Names() +func normalizedTag(tag string) (reference.Named, error) { decomposedTag, err := decompose(tag) if err != nil { - return "", err - } - // If the input does not have a tag, we need to add one (latest) - if !decomposedTag.isTagged { - tag = fmt.Sprintf("%s:%s", tag, decomposedTag.tag) + return nil, err } // If the input doesn't specify a registry, set the registry to localhost + var ref reference.Named if !decomposedTag.hasRegistry { - tag = fmt.Sprintf("%s/%s", DefaultLocalRegistry, tag) + ref, err = decomposedTag.referenceWithRegistry(DefaultLocalRegistry) + if err != nil { + return nil, err + } + } else { + ref, err = decomposedTag.normalizedReference() + if err != nil { + return nil, err + } } - return tag, nil + // If the input does not have a tag, we need to add one (latest) + ref = reference.TagNameOnly(ref) + return ref, nil } // TagImage adds a tag to the given image func (i *Image) TagImage(tag string) error { i.reloadImage() - tag, err := normalizeTag(tag) + ref, err := normalizedTag(tag) if err != nil { return err } tags := i.Names() - if util.StringInSlice(tag, tags) { + if util.StringInSlice(ref.String(), tags) { return nil } - tags = append(tags, tag) + tags = append(tags, ref.String()) if err := i.imageruntime.store.SetNames(i.ID(), tags); err != nil { return err } @@ -919,21 +930,23 @@ func (i *Image) MatchRepoTag(input string) (string, error) { if err != nil { return "", err } + imageRegistry, imageName, imageSuspiciousTagValueForSearch := dcImage.suspiciousRefNameTagValuesForSearch() for _, repoName := range i.Names() { count := 0 dcRepoName, err := decompose(repoName) if err != nil { return "", err } - if dcRepoName.registry == dcImage.registry && dcImage.registry != "" { + repoNameRegistry, repoNameName, repoNameSuspiciousTagValueForSearch := dcRepoName.suspiciousRefNameTagValuesForSearch() + if repoNameRegistry == imageRegistry && imageRegistry != "" { count++ } - if dcRepoName.name == dcImage.name && dcImage.name != "" { + if repoNameName == imageName && imageName != "" { count++ - } else if splitString(dcRepoName.name) == splitString(dcImage.name) { + } else if splitString(repoNameName) == splitString(imageName) { count++ } - if dcRepoName.tag == dcImage.tag { + if repoNameSuspiciousTagValueForSearch == imageSuspiciousTagValueForSearch { count++ } results[count] = append(results[count], repoName) diff --git a/libpod/image/image_test.go b/libpod/image/image_test.go index 91bb2411b..077ae460e 100644 --- a/libpod/image/image_test.go +++ b/libpod/image/image_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/containers/storage" + "github.com/opencontainers/go-digest" "github.com/stretchr/testify/assert" ) @@ -192,6 +193,51 @@ func TestImage_MatchRepoTag(t *testing.T) { cleanup(workdir, ir) } +// TestImage_RepoDigests tests RepoDigest generation. +func TestImage_RepoDigests(t *testing.T) { + dgst, err := digest.Parse("sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc") + if err != nil { + t.Fatal(err) + } + + for _, test := range []struct { + name string + names []string + expected []string + }{ + { + name: "empty", + names: []string{}, + expected: nil, + }, + { + name: "tagged", + names: []string{"docker.io/library/busybox:latest"}, + expected: []string{"docker.io/library/busybox@sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc"}, + }, + { + name: "digest", + names: []string{"docker.io/library/busybox@sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc"}, + expected: []string{"docker.io/library/busybox@sha256:7173b809ca12ec5dee4506cd86be934c4596dd234ee82c0662eac04a8c2c71dc"}, + }, + } { + t.Run(test.name, func(t *testing.T) { + image := &Image{ + image: &storage.Image{ + Names: test.names, + Digest: dgst, + }, + } + actual, err := image.RepoDigests() + if err != nil { + t.Fatal(err) + } + + assert.Equal(t, test.expected, actual) + }) + } +} + // Test_splitString tests the splitString function in image that // takes input and splits on / and returns the last array item func Test_splitString(t *testing.T) { @@ -211,24 +257,25 @@ func Test_stripSha256(t *testing.T) { assert.Equal(t, stripSha256("sha256:a"), "a") } -func TestNormalizeTag(t *testing.T) { +func TestNormalizedTag(t *testing.T) { const digestSuffix = "@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" for _, c := range []struct{ input, expected string }{ {"#", ""}, // Clearly invalid {"example.com/busybox", "example.com/busybox:latest"}, // Qualified name-only {"example.com/busybox:notlatest", "example.com/busybox:notlatest"}, // Qualified name:tag - {"example.com/busybox" + digestSuffix, "example.com/busybox" + digestSuffix + ":none"}, // Qualified name@digest; FIXME: The result is not even syntactically valid! + {"example.com/busybox" + digestSuffix, "example.com/busybox" + digestSuffix}, // Qualified name@digest; FIXME? Should we allow tagging with a digest at all? {"example.com/busybox:notlatest" + digestSuffix, "example.com/busybox:notlatest" + digestSuffix}, // Qualified name:tag@digest {"busybox:latest", "localhost/busybox:latest"}, // Unqualified name-only {"ns/busybox:latest", "localhost/ns/busybox:latest"}, // Unqualified with a dot-less namespace + {"docker.io/busybox:latest", "docker.io/library/busybox:latest"}, // docker.io without /library/ } { - res, err := normalizeTag(c.input) + res, err := normalizedTag(c.input) if c.expected == "" { assert.Error(t, err, c.input) } else { assert.NoError(t, err, c.input) - assert.Equal(t, c.expected, res) + assert.Equal(t, c.expected, res.String()) } } } diff --git a/libpod/image/parts.go b/libpod/image/parts.go index 1509005e5..dfdf0b08a 100644 --- a/libpod/image/parts.go +++ b/libpod/image/parts.go @@ -1,79 +1,104 @@ package image import ( - "fmt" "strings" "github.com/containers/image/docker/reference" + "github.com/pkg/errors" ) // imageParts describes the parts of an image's name type imageParts struct { - transport string - registry string - name string - tag string - isTagged bool - hasRegistry bool + unnormalizedRef reference.Named // WARNING: Did not go through docker.io[/library] normalization + hasRegistry bool } -// Registries must contain a ":" or a "." or be localhost +// Registries must contain a ":" or a "." or be localhost; this helper exists for users of reference.Parse. +// For inputs that should use the docker.io[/library] normalization, use reference.ParseNormalizedNamed instead. func isRegistry(name string) bool { return strings.ContainsAny(name, ".:") || name == "localhost" } +// GetImageBaseName uses decompose and string splits to obtain the base +// name of an image. Doing this here because it beats changing the +// imageParts struct names to be exported as well. +func GetImageBaseName(input string) (string, error) { + decomposedImage, err := decompose(input) + if err != nil { + return "", err + } + splitImageName := strings.Split(decomposedImage.unnormalizedRef.Name(), "/") + return splitImageName[len(splitImageName)-1], nil +} + // decompose breaks an input name into an imageParts description func decompose(input string) (imageParts, error) { - var ( - parts imageParts - hasRegistry bool - tag string - ) imgRef, err := reference.Parse(input) if err != nil { - return parts, err - } - ntag, isTagged := imgRef.(reference.NamedTagged) - if !isTagged { - tag = "latest" - if _, hasDigest := imgRef.(reference.Digested); hasDigest { - tag = "none" - } - } else { - tag = ntag.Tag() - } - registry := reference.Domain(imgRef.(reference.Named)) - imageName := reference.Path(imgRef.(reference.Named)) - // Is this a registry or a repo? - if isRegistry(registry) { - hasRegistry = true - } else { - if registry != "" { - imageName = registry + "/" + imageName - registry = "" - } + return imageParts{}, err } + unnormalizedNamed := imgRef.(reference.Named) + // ip.unnormalizedRef, because it uses reference.Parse and not reference.ParseNormalizedNamed, + // does not use the standard heuristics for domains vs. namespaces/repos, so we need to check + // explicitly. + hasRegistry := isRegistry(reference.Domain(unnormalizedNamed)) return imageParts{ - registry: registry, - hasRegistry: hasRegistry, - name: imageName, - tag: tag, - isTagged: isTagged, - transport: DefaultTransport, + unnormalizedRef: unnormalizedNamed, + hasRegistry: hasRegistry, }, nil } -// assemble concatenates an image's parts into a string -func (ip *imageParts) assemble() string { - spec := fmt.Sprintf("%s:%s", ip.name, ip.tag) +// suspiciousRefNameTagValuesForSearch returns a "tag" value used in a previous implementation. +// This exists only to preserve existing behavior in heuristic code; it’s dubious that that behavior is correct, +// gespecially for the tag value. +func (ip *imageParts) suspiciousRefNameTagValuesForSearch() (string, string, string) { + registry := reference.Domain(ip.unnormalizedRef) + imageName := reference.Path(ip.unnormalizedRef) + // ip.unnormalizedRef, because it uses reference.Parse and not reference.ParseNormalizedNamed, + // does not use the standard heuristics for domains vs. namespaces/repos. + if registry != "" && !isRegistry(registry) { + imageName = registry + "/" + imageName + registry = "" + } - if ip.registry != "" { - spec = fmt.Sprintf("%s/%s", ip.registry, spec) + var tag string + if tagged, isTagged := ip.unnormalizedRef.(reference.NamedTagged); isTagged { + tag = tagged.Tag() + } else if _, hasDigest := ip.unnormalizedRef.(reference.Digested); hasDigest { + tag = "none" + } else { + tag = "latest" } - return spec + return registry, imageName, tag } -// assemble concatenates an image's parts with transport into a string -func (ip *imageParts) assembleWithTransport() string { - return fmt.Sprintf("%s%s", ip.transport, ip.assemble()) +// referenceWithRegistry returns a (normalized) reference.Named composed of ip (with !ip.hasRegistry) +// qualified with registry. +func (ip *imageParts) referenceWithRegistry(registry string) (reference.Named, error) { + if ip.hasRegistry { + return nil, errors.Errorf("internal error: referenceWithRegistry called on imageParts with a registry (%#v)", *ip) + } + // We could build a reference.WithName+WithTag/WithDigest here, but we need to round-trip via a string + // and a ParseNormalizedNamed anyway to get the right normalization of docker.io/library, so + // just use a string directly. + qualified := registry + "/" + ip.unnormalizedRef.String() + ref, err := reference.ParseNormalizedNamed(qualified) + if err != nil { + return nil, errors.Wrapf(err, "error normalizing registry+unqualified reference %#v", qualified) + } + return ref, nil +} + +// normalizedReference returns a (normalized) reference for ip (with ip.hasRegistry) +func (ip *imageParts) normalizedReference() (reference.Named, error) { + if !ip.hasRegistry { + return nil, errors.Errorf("internal error: normalizedReference called on imageParts without a registry (%#v)", *ip) + } + // We need to round-trip via a string to get the right normalization of docker.io/library + s := ip.unnormalizedRef.String() + ref, err := reference.ParseNormalizedNamed(s) + if err != nil { // Should never happen + return nil, errors.Wrapf(err, "error normalizing qualified reference %#v", s) + } + return ref, nil } diff --git a/libpod/image/parts_test.go b/libpod/image/parts_test.go index 518538f0b..726e55e86 100644 --- a/libpod/image/parts_test.go +++ b/libpod/image/parts_test.go @@ -4,64 +4,120 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestDecompose(t *testing.T) { const digestSuffix = "@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" for _, c := range []struct { - input string - transport, registry, name, tag string - isTagged, hasRegistry bool - assembled string - assembledWithTransport string + input string + registry, name, suspiciousTagValueForSearch string + hasRegistry bool }{ - {"#", "", "", "", "", false, false, "", ""}, // Entirely invalid input + {"#", "", "", "", false}, // Entirely invalid input { // Fully qualified docker.io, name-only input - "docker.io/library/busybox", "docker://", "docker.io", "library/busybox", "latest", false, true, - "docker.io/library/busybox:latest", "docker://docker.io/library/busybox:latest", + "docker.io/library/busybox", "docker.io", "library/busybox", "latest", true, }, { // Fully qualified example.com, name-only input - "example.com/ns/busybox", "docker://", "example.com", "ns/busybox", "latest", false, true, - "example.com/ns/busybox:latest", "docker://example.com/ns/busybox:latest", + "example.com/ns/busybox", "example.com", "ns/busybox", "latest", true, }, { // Unqualified single-name input - "busybox", "docker://", "", "busybox", "latest", false, false, - "busybox:latest", "docker://busybox:latest", + "busybox", "", "busybox", "latest", false, }, { // Unqualified namespaced input - "ns/busybox", "docker://", "", "ns/busybox", "latest", false, false, - "ns/busybox:latest", "docker://ns/busybox:latest", + "ns/busybox", "", "ns/busybox", "latest", false, }, { // name:tag - "example.com/ns/busybox:notlatest", "docker://", "example.com", "ns/busybox", "notlatest", true, true, - "example.com/ns/busybox:notlatest", "docker://example.com/ns/busybox:notlatest", + "example.com/ns/busybox:notlatest", "example.com", "ns/busybox", "notlatest", true, }, { // name@digest - // FIXME? .tag == "none" - "example.com/ns/busybox" + digestSuffix, "docker://", "example.com", "ns/busybox", "none", false, true, - // FIXME: this drops the digest and replaces it with an incorrect tag. - "example.com/ns/busybox:none", "docker://example.com/ns/busybox:none", + // FIXME? .suspiciousTagValueForSearch == "none" + "example.com/ns/busybox" + digestSuffix, "example.com", "ns/busybox", "none", true, }, { // name:tag@digest - "example.com/ns/busybox:notlatest" + digestSuffix, "docker://", "example.com", "ns/busybox", "notlatest", true, true, - // FIXME: This drops the digest - "example.com/ns/busybox:notlatest", "docker://example.com/ns/busybox:notlatest", + "example.com/ns/busybox:notlatest" + digestSuffix, "example.com", "ns/busybox", "notlatest", true, }, } { parts, err := decompose(c.input) - if c.transport == "" { + if c.name == "" { assert.Error(t, err, c.input) } else { assert.NoError(t, err, c.input) - assert.Equal(t, c.transport, parts.transport, c.input) - assert.Equal(t, c.registry, parts.registry, c.input) - assert.Equal(t, c.name, parts.name, c.input) - assert.Equal(t, c.tag, parts.tag, c.input) - assert.Equal(t, c.isTagged, parts.isTagged, c.input) + registry, name, suspiciousTagValueForSearch := parts.suspiciousRefNameTagValuesForSearch() + assert.Equal(t, c.registry, registry, c.input) + assert.Equal(t, c.name, name, c.input) + assert.Equal(t, c.suspiciousTagValueForSearch, suspiciousTagValueForSearch, c.input) assert.Equal(t, c.hasRegistry, parts.hasRegistry, c.input) - assert.Equal(t, c.assembled, parts.assemble(), c.input) - assert.Equal(t, c.assembledWithTransport, parts.assembleWithTransport(), c.input) + } + } +} + +func TestImagePartsReferenceWithRegistry(t *testing.T) { + const digestSuffix = "@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + + for _, c := range []struct { + input string + withDocker, withNonDocker string + }{ + {"example.com/ns/busybox", "", ""}, // Fully-qualified input is invalid. + {"busybox", "docker.io/library/busybox", "example.com/busybox"}, // Single-name input + {"ns/busybox", "docker.io/ns/busybox", "example.com/ns/busybox"}, // Namespaced input + {"ns/busybox:notlatest", "docker.io/ns/busybox:notlatest", "example.com/ns/busybox:notlatest"}, // name:tag + {"ns/busybox" + digestSuffix, "docker.io/ns/busybox" + digestSuffix, "example.com/ns/busybox" + digestSuffix}, // name@digest + { // name:tag@digest + "ns/busybox:notlatest" + digestSuffix, + "docker.io/ns/busybox:notlatest" + digestSuffix, "example.com/ns/busybox:notlatest" + digestSuffix, + }, + } { + parts, err := decompose(c.input) + require.NoError(t, err) + if c.withDocker == "" { + _, err := parts.referenceWithRegistry("docker.io") + assert.Error(t, err, c.input) + _, err = parts.referenceWithRegistry("example.com") + assert.Error(t, err, c.input) + } else { + ref, err := parts.referenceWithRegistry("docker.io") + require.NoError(t, err, c.input) + assert.Equal(t, c.withDocker, ref.String()) + ref, err = parts.referenceWithRegistry("example.com") + require.NoError(t, err, c.input) + assert.Equal(t, c.withNonDocker, ref.String()) + } + } + + // Invalid registry value + parts, err := decompose("busybox") + require.NoError(t, err) + _, err = parts.referenceWithRegistry("invalid@domain") + assert.Error(t, err) +} + +func TestImagePartsNormalizedReference(t *testing.T) { + const digestSuffix = "@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + + for _, c := range []struct{ input, expected string }{ + {"busybox", ""}, // Unqualified input is invalid + {"docker.io/busybox", "docker.io/library/busybox"}, // docker.io single-name + {"example.com/busybox", "example.com/busybox"}, // example.com single-name + {"docker.io/ns/busybox", "docker.io/ns/busybox"}, // docker.io namespaced + {"example.com/ns/busybox", "example.com/ns/busybox"}, // example.com namespaced + {"example.com/ns/busybox:notlatest", "example.com/ns/busybox:notlatest"}, // name:tag + {"example.com/ns/busybox" + digestSuffix, "example.com/ns/busybox" + digestSuffix}, // name@digest + { // name:tag@digest + "example.com/ns/busybox:notlatest" + digestSuffix, "example.com/ns/busybox:notlatest" + digestSuffix, + }, + } { + parts, err := decompose(c.input) + require.NoError(t, err) + if c.expected == "" { + _, err := parts.normalizedReference() + assert.Error(t, err, c.input) + } else { + ref, err := parts.normalizedReference() + require.NoError(t, err, c.input) + assert.Equal(t, c.expected, ref.String()) } } } diff --git a/libpod/image/pull.go b/libpod/image/pull.go index 09935fe7c..434b83520 100644 --- a/libpod/image/pull.go +++ b/libpod/image/pull.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "io" - "strings" cp "github.com/containers/image/copy" "github.com/containers/image/directory" @@ -76,9 +75,11 @@ func (ir *Runtime) getPullRefPair(srcRef types.ImageReference, destName string) decomposedDest, err := decompose(destName) if err == nil && !decomposedDest.hasRegistry { // If the image doesn't have a registry, set it as the default repo - decomposedDest.registry = DefaultLocalRegistry - decomposedDest.hasRegistry = true - destName = decomposedDest.assemble() + ref, err := decomposedDest.referenceWithRegistry(DefaultLocalRegistry) + if err != nil { + return pullRefPair{}, err + } + destName = ref.String() } reference := destName @@ -270,12 +271,6 @@ func (ir *Runtime) doPullImage(ctx context.Context, sc *types.SystemContext, goa return images, nil } -// hasShaInInputName returns a bool as to whether the user provided an image name that includes -// a reference to a specific sha -func hasShaInInputName(inputName string) bool { - return strings.Contains(inputName, "@sha256:") -} - // pullGoalFromPossiblyUnqualifiedName looks at inputName and determines the possible // image references to try pulling in combination with the registries.conf file as well func (ir *Runtime) pullGoalFromPossiblyUnqualifiedName(inputName string) (*pullGoal, error) { @@ -284,31 +279,11 @@ func (ir *Runtime) pullGoalFromPossiblyUnqualifiedName(inputName string) (*pullG return nil, err } if decomposedImage.hasRegistry { - var imageName, destName string - if hasShaInInputName(inputName) { - imageName = fmt.Sprintf("%s%s", decomposedImage.transport, inputName) - } else { - imageName = decomposedImage.assembleWithTransport() - } - srcRef, err := alltransports.ParseImageName(imageName) + srcRef, err := docker.ParseReference("//" + inputName) if err != nil { return nil, errors.Wrapf(err, "unable to parse '%s'", inputName) } - if hasShaInInputName(inputName) { - destName = decomposedImage.assemble() - } else { - destName = inputName - } - destRef, err := is.Transport.ParseStoreReference(ir.store, destName) - if err != nil { - return nil, errors.Wrapf(err, "error parsing dest reference name %#v", destName) - } - ps := pullRefPair{ - image: inputName, - srcRef: srcRef, - dstRef: destRef, - } - return singlePullRefPairGoal(ps), nil + return ir.getSinglePullRefPairGoal(srcRef, inputName) } searchRegistries, err := registries.GetRegistries() @@ -317,22 +292,18 @@ func (ir *Runtime) pullGoalFromPossiblyUnqualifiedName(inputName string) (*pullG } var refPairs []pullRefPair for _, registry := range searchRegistries { - decomposedImage.registry = registry - imageName := decomposedImage.assembleWithTransport() - if hasShaInInputName(inputName) { - imageName = fmt.Sprintf("%s%s/%s", decomposedImage.transport, registry, inputName) - } - srcRef, err := alltransports.ParseImageName(imageName) + ref, err := decomposedImage.referenceWithRegistry(registry) if err != nil { - return nil, errors.Wrapf(err, "unable to parse '%s'", inputName) + return nil, err } - ps := pullRefPair{ - image: decomposedImage.assemble(), - srcRef: srcRef, + imageName := ref.String() + srcRef, err := docker.ParseReference("//" + imageName) + if err != nil { + return nil, errors.Wrapf(err, "unable to parse '%s'", imageName) } - ps.dstRef, err = is.Transport.ParseStoreReference(ir.store, ps.image) + ps, err := ir.getPullRefPair(srcRef, imageName) if err != nil { - return nil, errors.Wrapf(err, "error parsing dest reference name %#v", ps.image) + return nil, err } refPairs = append(refPairs, ps) } diff --git a/libpod/image/pull_test.go b/libpod/image/pull_test.go index 37b45dc83..3890c5e6c 100644 --- a/libpod/image/pull_test.go +++ b/libpod/image/pull_test.go @@ -76,9 +76,7 @@ func TestGetPullRefPair(t *testing.T) { }, { // name, no registry, no tag: "dir:/dev/this-does-not-exist", "from-directory", - // FIXME(?) Adding a registry also adds a :latest tag. OTOH that actually matches the used destination. - // Either way it is surprising that the localhost/ addition changes this. (mitr hoping to remove the "image" member). - "localhost/from-directory:latest", "localhost/from-directory:latest", + "localhost/from-directory", "localhost/from-directory:latest", }, { // registry/name:tag : "dir:/dev/this-does-not-exist", "example.com/from-directory:notlatest", @@ -90,8 +88,7 @@ func TestGetPullRefPair(t *testing.T) { }, { // name@digest, no registry: "dir:/dev/this-does-not-exist", "from-directory" + digestSuffix, - // FIXME?! Why is this dropping the digest, and adding :none?! - "localhost/from-directory:none", "localhost/from-directory:none", + "localhost/from-directory" + digestSuffix, "localhost/from-directory" + digestSuffix, }, { // registry/name@digest: "dir:/dev/this-does-not-exist", "example.com/from-directory" + digestSuffix, @@ -211,14 +208,13 @@ func TestPullGoalFromImageReference(t *testing.T) { false, }, { // Relative path, single element. - // FIXME? Note the :latest difference in .image. "dir:this-does-not-exist", - []expected{{"localhost/this-does-not-exist:latest", "localhost/this-does-not-exist:latest"}}, + []expected{{"localhost/this-does-not-exist", "localhost/this-does-not-exist:latest"}}, false, }, { // Relative path, multiple elements. "dir:testdata/this-does-not-exist", - []expected{{"localhost/testdata/this-does-not-exist:latest", "localhost/testdata/this-does-not-exist:latest"}}, + []expected{{"localhost/testdata/this-does-not-exist", "localhost/testdata/this-does-not-exist:latest"}}, false, }, @@ -324,8 +320,7 @@ func TestPullGoalFromPossiblyUnqualifiedName(t *testing.T) { { // Qualified example.com, name@digest. "example.com/ns/busybox" + digestSuffix, []pullRefStrings{{"example.com/ns/busybox" + digestSuffix, "docker://example.com/ns/busybox" + digestSuffix, - // FIXME?! Why is .dstName dropping the digest, and adding :none?! - "example.com/ns/busybox:none"}}, + "example.com/ns/busybox" + digestSuffix}}, false, }, // Qualified example.com, name:tag@digest. This code is happy to try, but .srcRef parsing currently rejects such input. @@ -333,16 +328,16 @@ func TestPullGoalFromPossiblyUnqualifiedName(t *testing.T) { { // Unqualified, single-name, name-only "busybox", []pullRefStrings{ - {"example.com/busybox:latest", "docker://example.com/busybox:latest", "example.com/busybox:latest"}, + {"example.com/busybox", "docker://example.com/busybox:latest", "example.com/busybox:latest"}, // (The docker:// representation is shortened by c/image/docker.Reference but it refers to "docker.io/library".) - {"docker.io/busybox:latest", "docker://busybox:latest", "docker.io/library/busybox:latest"}, + {"docker.io/library/busybox", "docker://busybox:latest", "docker.io/library/busybox:latest"}, }, true, }, { // Unqualified, namespaced, name-only "ns/busybox", []pullRefStrings{ - {"example.com/ns/busybox:latest", "docker://example.com/ns/busybox:latest", "example.com/ns/busybox:latest"}, + {"example.com/ns/busybox", "docker://example.com/ns/busybox:latest", "example.com/ns/busybox:latest"}, }, true, }, @@ -351,17 +346,16 @@ func TestPullGoalFromPossiblyUnqualifiedName(t *testing.T) { []pullRefStrings{ {"example.com/busybox:notlatest", "docker://example.com/busybox:notlatest", "example.com/busybox:notlatest"}, // (The docker:// representation is shortened by c/image/docker.Reference but it refers to "docker.io/library".) - {"docker.io/busybox:notlatest", "docker://busybox:notlatest", "docker.io/library/busybox:notlatest"}, + {"docker.io/library/busybox:notlatest", "docker://busybox:notlatest", "docker.io/library/busybox:notlatest"}, }, true, }, { // Unqualified, name@digest "busybox" + digestSuffix, []pullRefStrings{ - // FIXME?! Why is .input and .dstName dropping the digest, and adding :none?! - {"example.com/busybox:none", "docker://example.com/busybox" + digestSuffix, "example.com/busybox:none"}, + {"example.com/busybox" + digestSuffix, "docker://example.com/busybox" + digestSuffix, "example.com/busybox" + digestSuffix}, // (The docker:// representation is shortened by c/image/docker.Reference but it refers to "docker.io/library".) - {"docker.io/busybox:none", "docker://busybox" + digestSuffix, "docker.io/library/busybox:none"}, + {"docker.io/library/busybox" + digestSuffix, "docker://busybox" + digestSuffix, "docker.io/library/busybox" + digestSuffix}, }, true, }, diff --git a/libpod/image/utils.go b/libpod/image/utils.go index b944de1bb..ad027f32a 100644 --- a/libpod/image/utils.go +++ b/libpod/image/utils.go @@ -17,6 +17,7 @@ import ( // findImageInRepotags takes an imageParts struct and searches images' repotags for // a match on name:tag func findImageInRepotags(search imageParts, images []*Image) (*storage.Image, error) { + _, searchName, searchSuspiciousTagValueForSearch := search.suspiciousRefNameTagValuesForSearch() var results []*storage.Image for _, image := range images { for _, name := range image.Names() { @@ -25,21 +26,22 @@ func findImageInRepotags(search imageParts, images []*Image) (*storage.Image, er if err != nil { continue } - if d.name == search.name && d.tag == search.tag { + _, dName, dSuspiciousTagValueForSearch := d.suspiciousRefNameTagValuesForSearch() + if dName == searchName && dSuspiciousTagValueForSearch == searchSuspiciousTagValueForSearch { results = append(results, image.image) continue } // account for registry:/somedir/image - if strings.HasSuffix(d.name, search.name) && d.tag == search.tag { + if strings.HasSuffix(dName, searchName) && dSuspiciousTagValueForSearch == searchSuspiciousTagValueForSearch { results = append(results, image.image) continue } } } if len(results) == 0 { - return &storage.Image{}, errors.Errorf("unable to find a name and tag match for %s in repotags", search.name) + return &storage.Image{}, errors.Errorf("unable to find a name and tag match for %s in repotags", searchName) } else if len(results) > 1 { - return &storage.Image{}, errors.Errorf("found multiple name and tag matches for %s in repotags", search.name) + return &storage.Image{}, errors.Errorf("found multiple name and tag matches for %s in repotags", searchName) } return results[0], nil } diff --git a/libpod/info.go b/libpod/info.go index 7044eba6a..191ce6810 100644 --- a/libpod/info.go +++ b/libpod/info.go @@ -4,7 +4,6 @@ import ( "bufio" "bytes" "fmt" - "github.com/containers/buildah" "io/ioutil" "os" "runtime" @@ -12,7 +11,9 @@ import ( "strings" "time" + "github.com/containers/buildah" "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/util" "github.com/containers/libpod/utils" "github.com/containers/storage/pkg/system" "github.com/pkg/errors" @@ -115,6 +116,7 @@ func (r *Runtime) hostInfo() (map[string]interface{}, error) { func (r *Runtime) storeInfo() (map[string]interface{}, error) { // lets say storage driver in use, number of images, number of containers info := map[string]interface{}{} + info["ConfigFile"] = util.StorageConfigFile() info["GraphRoot"] = r.store.GraphRoot() info["RunRoot"] = r.store.RunRoot() info["GraphDriverName"] = r.store.GraphDriverName() @@ -182,12 +184,12 @@ func (r *Runtime) GetConmonVersion() (string, error) { // GetOCIRuntimePath returns the path to the OCI Runtime Path the runtime is using func (r *Runtime) GetOCIRuntimePath() string { - return r.ociRuntimePath + return r.ociRuntimePath.Paths[0] } // GetOCIRuntimeVersion returns a string representation of the oci runtimes version func (r *Runtime) GetOCIRuntimeVersion() (string, error) { - output, err := utils.ExecCmd(r.ociRuntimePath, "--version") + output, err := utils.ExecCmd(r.ociRuntimePath.Paths[0], "--version") if err != nil { return "", err } diff --git a/libpod/lock/in_memory_locks.go b/libpod/lock/in_memory_locks.go new file mode 100644 index 000000000..db8f20e95 --- /dev/null +++ b/libpod/lock/in_memory_locks.go @@ -0,0 +1,91 @@ +package lock + +import ( + "sync" + + "github.com/pkg/errors" +) + +// Mutex holds a single mutex and whether it has been allocated. +type Mutex struct { + id uint32 + lock sync.Mutex + allocated bool +} + +// ID retrieves the ID of the mutex +func (m *Mutex) ID() uint32 { + return m.id +} + +// Lock locks the mutex +func (m *Mutex) Lock() { + m.lock.Lock() +} + +// Unlock unlocks the mutex +func (m *Mutex) Unlock() { + m.lock.Unlock() +} + +// Free deallocates the mutex to allow its reuse +func (m *Mutex) Free() error { + m.allocated = false + + return nil +} + +// InMemoryManager is a lock manager that allocates and retrieves local-only +// locks - that is, they are not multiprocess. This lock manager is intended +// purely for unit and integration testing and should not be used in production +// deployments. +type InMemoryManager struct { + locks []*Mutex + numLocks uint32 + localLock sync.Mutex +} + +// NewInMemoryManager creates a new in-memory lock manager with the given number +// of locks. +func NewInMemoryManager(numLocks uint32) (Manager, error) { + if numLocks == 0 { + return nil, errors.Errorf("must provide a non-zero number of locks!") + } + + manager := new(InMemoryManager) + manager.numLocks = numLocks + manager.locks = make([]*Mutex, numLocks) + + var i uint32 + for i = 0; i < numLocks; i++ { + lock := new(Mutex) + lock.id = i + manager.locks[i] = lock + } + + return manager, nil +} + +// AllocateLock allocates a lock from the manager. +func (m *InMemoryManager) AllocateLock() (Locker, error) { + m.localLock.Lock() + defer m.localLock.Unlock() + + for _, lock := range m.locks { + if !lock.allocated { + lock.allocated = true + return lock, nil + } + } + + return nil, errors.Errorf("all locks have been allocated") +} + +// RetrieveLock retrieves a lock from the manager. +func (m *InMemoryManager) RetrieveLock(id uint32) (Locker, error) { + if id >= m.numLocks { + return nil, errors.Errorf("given lock ID %d is too large - this manager only supports lock indexes up to %d", id, m.numLocks-1) + } + + return m.locks[id], nil +} diff --git a/libpod/lock/lock.go b/libpod/lock/lock.go new file mode 100644 index 000000000..1f94171fe --- /dev/null +++ b/libpod/lock/lock.go @@ -0,0 +1,61 @@ +package lock + +// Manager provides an interface for allocating multiprocess locks. +// Locks returned by Manager MUST be multiprocess - allocating a lock in +// process A and retrieving that lock's ID in process B must return handles for +// the same lock, and locking the lock in A should exclude B from the lock until +// it is unlocked in A. +// All locks must be identified by a UUID (retrieved with Locker's ID() method). +// All locks with a given UUID must refer to the same underlying lock, and it +// must be possible to retrieve the lock given its UUID. +// Each UUID should refer to a unique underlying lock. +// Calls to AllocateLock() must return a unique, unallocated UUID. +// AllocateLock() must fail once all available locks have been allocated. +// Locks are returned to use by calls to Free(), and can subsequently be +// reallocated. +type Manager interface { + // AllocateLock returns an unallocated lock. + // It is guaranteed that the same lock will not be returned again by + // AllocateLock until the returned lock has Free() called on it. + // If all available locks are allocated, AllocateLock will return an + // error. + AllocateLock() (Locker, error) + // RetrieveLock retrieves a lock given its UUID. + // The underlying lock MUST be the same as another other lock with the + // same UUID. + RetrieveLock(id uint32) (Locker, error) +} + +// Locker is similar to sync.Locker, but provides a method for freeing the lock +// to allow its reuse. +// All Locker implementations must maintain mutex semantics - the lock only +// allows one caller in the critical section at a time. +// All locks with the same ID must refer to the same underlying lock, even +// if they are within multiple processes. +type Locker interface { + // ID retrieves the lock's ID. + // ID is guaranteed to uniquely identify the lock within the + // Manager - that is, calling RetrieveLock with this ID will return + // another instance of the same lock. + ID() uint32 + // Lock locks the lock. + // This call MUST block until it successfully acquires the lock or + // encounters a fatal error. + // All errors must be handled internally, as they are not returned. For + // the most part, panicking should be appropriate. + // Some lock implementations may require that Lock() and Unlock() occur + // within the same goroutine (SHM locking, for example). The usual Go + // Lock()/defer Unlock() pattern will still work fine in these cases. + Lock() + // Unlock unlocks the lock. + // All errors must be handled internally, as they are not returned. For + // the most part, panicking should be appropriate. + // This includes unlocking locks which are already unlocked. + Unlock() + // Free deallocates the underlying lock, allowing its reuse by other + // pods and containers. + // The lock MUST still be usable after a Free() - some libpod instances + // may still retain Container structs with the old lock. This simply + // advises the manager that the lock may be reallocated. + Free() error +} diff --git a/libpod/lock/shm/shm_lock.c b/libpod/lock/shm/shm_lock.c new file mode 100644 index 000000000..4af58d857 --- /dev/null +++ b/libpod/lock/shm/shm_lock.c @@ -0,0 +1,452 @@ +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "shm_lock.h" + +// Compute the size of the SHM struct +static size_t compute_shm_size(uint32_t num_bitmaps) { + return sizeof(shm_struct_t) + (num_bitmaps * sizeof(lock_group_t)); +} + +// Take the given mutex. +// Handles exceptional conditions, including a mutex locked by a process that +// died holding it. +// Returns 0 on success, or positive errno on failure. +static int take_mutex(pthread_mutex_t *mutex) { + int ret_code; + + do { + ret_code = pthread_mutex_lock(mutex); + } while(ret_code == EAGAIN); + + if (ret_code == EOWNERDEAD) { + // The previous owner of the mutex died while holding it + // Take it for ourselves + ret_code = pthread_mutex_consistent(mutex); + if (ret_code != 0) { + // Someone else may have gotten here first and marked the state consistent + // However, the mutex could also be invalid. + // Fail here instead of looping back to trying to lock the mutex. + return ret_code; + } + } else if (ret_code != 0) { + return ret_code; + } + + return 0; +} + +// Release the given mutex. +// Returns 0 on success, or positive errno on failure. +static int release_mutex(pthread_mutex_t *mutex) { + int ret_code; + + do { + ret_code = pthread_mutex_unlock(mutex); + } while(ret_code == EAGAIN); + + if (ret_code != 0) { + return ret_code; + } + + return 0; +} + +// Set up an SHM segment holding locks for libpod. +// num_locks must not be 0. +// Path is the path to the SHM segment. It must begin with a single / and +// container no other / characters, and be at most 255 characters including +// terminating NULL byte. +// Returns a valid pointer on success or NULL on error. +// If an error occurs, negative ERRNO values will be written to error_code. +shm_struct_t *setup_lock_shm(char *path, uint32_t num_locks, int *error_code) { + int shm_fd, i, j, ret_code; + uint32_t num_bitmaps; + size_t shm_size; + shm_struct_t *shm; + pthread_mutexattr_t attr; + + // If error_code doesn't point to anything, we can't reasonably return errors + // So fail immediately + if (error_code == NULL) { + return NULL; + } + + // We need a nonzero number of locks + if (num_locks == 0) { + *error_code = -1 * EINVAL; + return NULL; + } + + if (path == NULL) { + *error_code = -1 * EINVAL; + return NULL; + } + + // Calculate the number of bitmaps required + num_bitmaps = num_locks / BITMAP_SIZE; + if (num_locks % BITMAP_SIZE != 0) { + // The actual number given is not an even multiple of our bitmap size + // So round up + num_bitmaps += 1; + } + + // Calculate size of the shm segment + shm_size = compute_shm_size(num_bitmaps); + + // Create a new SHM segment for us + shm_fd = shm_open(path, O_RDWR | O_CREAT | O_EXCL, 0600); + if (shm_fd < 0) { + *error_code = -1 * errno; + return NULL; + } + + // Increase its size to what we need + ret_code = ftruncate(shm_fd, shm_size); + if (ret_code < 0) { + *error_code = -1 * errno; + goto CLEANUP_UNLINK; + } + + // Map the shared memory in + shm = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + if (shm == MAP_FAILED) { + *error_code = -1 * errno; + goto CLEANUP_UNLINK; + } + + // We have successfully mapped the memory, now initialize the region + shm->magic = MAGIC; + shm->unused = 0; + shm->num_locks = num_bitmaps * BITMAP_SIZE; + shm->num_bitmaps = num_bitmaps; + + // Create an initializer for our pthread mutexes + ret_code = pthread_mutexattr_init(&attr); + if (ret_code != 0) { + *error_code = -1 * ret_code; + goto CLEANUP_UNMAP; + } + + // Set mutexes to pshared - multiprocess-safe + ret_code = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); + if (ret_code != 0) { + *error_code = -1 * ret_code; + goto CLEANUP_FREEATTR; + } + + // Set mutexes to robust - if a process dies while holding a mutex, we'll get + // a special error code on the next attempt to lock it. + // This should prevent panicing processes from leaving the state unusable. + ret_code = pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST); + if (ret_code != 0) { + *error_code = -1 * ret_code; + goto CLEANUP_FREEATTR; + } + + // Initialize the mutex that protects the bitmaps using the mutex attributes + ret_code = pthread_mutex_init(&(shm->segment_lock), &attr); + if (ret_code != 0) { + *error_code = -1 * ret_code; + goto CLEANUP_FREEATTR; + } + + // Initialize all bitmaps to 0 initially + // And initialize all semaphores they use + for (i = 0; i < num_bitmaps; i++) { + shm->locks[i].bitmap = 0; + for (j = 0; j < BITMAP_SIZE; j++) { + // Initialize each mutex + ret_code = pthread_mutex_init(&(shm->locks[i].locks[j]), &attr); + if (ret_code != 0) { + *error_code = -1 * ret_code; + goto CLEANUP_FREEATTR; + } + } + } + + // Close the file descriptor, we're done with it + // Ignore errors, it's ok if we leak a single FD and this should only run once + close(shm_fd); + + // Destroy the pthread initializer attribute. + // Again, ignore errors, this will only run once and we might leak a tiny bit + // of memory at worst. + pthread_mutexattr_destroy(&attr); + + return shm; + + // Cleanup after an error + CLEANUP_FREEATTR: + pthread_mutexattr_destroy(&attr); + CLEANUP_UNMAP: + munmap(shm, shm_size); + CLEANUP_UNLINK: + close(shm_fd); + shm_unlink(path); + return NULL; +} + +// Open an existing SHM segment holding libpod locks. +// num_locks is the number of locks that will be configured in the SHM segment. +// num_locks cannot be 0. +// Path is the path to the SHM segment. It must begin with a single / and +// container no other / characters, and be at most 255 characters including +// terminating NULL byte. +// Returns a valid pointer on success or NULL on error. +// If an error occurs, negative ERRNO values will be written to error_code. +shm_struct_t *open_lock_shm(char *path, uint32_t num_locks, int *error_code) { + int shm_fd; + shm_struct_t *shm; + size_t shm_size; + uint32_t num_bitmaps; + + if (error_code == NULL) { + return NULL; + } + + // We need a nonzero number of locks + if (num_locks == 0) { + *error_code = -1 * EINVAL; + return NULL; + } + + if (path == NULL) { + *error_code = -1 * EINVAL; + return NULL; + } + + // Calculate the number of bitmaps required + num_bitmaps = num_locks / BITMAP_SIZE; + if (num_locks % BITMAP_SIZE != 0) { + num_bitmaps += 1; + } + + // Calculate size of the shm segment + shm_size = compute_shm_size(num_bitmaps); + + shm_fd = shm_open(path, O_RDWR, 0600); + if (shm_fd < 0) { + *error_code = -1 * errno; + return NULL; + } + + // Map the shared memory in + shm = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + if (shm == MAP_FAILED) { + *error_code = -1 * errno; + } + + // Ignore errors, it's ok if we leak a single FD since this only runs once + close(shm_fd); + + // Check if we successfully mmap'd + if (shm == MAP_FAILED) { + return NULL; + } + + // Need to check the SHM to see if it's actually our locks + if (shm->magic != MAGIC) { + *error_code = -1 * errno; + goto CLEANUP; + } + if (shm->num_locks != (num_bitmaps * BITMAP_SIZE)) { + *error_code = -1 * errno; + goto CLEANUP; + } + + return shm; + + CLEANUP: + munmap(shm, shm_size); + return NULL; +} + +// Close an open SHM lock struct, unmapping the backing memory. +// The given shm_struct_t will be rendered unusable as a result. +// On success, 0 is returned. On failure, negative ERRNO values are returned. +int32_t close_lock_shm(shm_struct_t *shm) { + int ret_code; + size_t shm_size; + + // We can't unmap null... + if (shm == NULL) { + return -1 * EINVAL; + } + + shm_size = compute_shm_size(shm->num_bitmaps); + + ret_code = munmap(shm, shm_size); + + if (ret_code != 0) { + return -1 * errno; + } + + return 0; +} + +// Allocate the first available semaphore +// Returns a positive integer guaranteed to be less than UINT32_MAX on success, +// or negative errno values on failure +// On sucess, the returned integer is the number of the semaphore allocated +int64_t allocate_semaphore(shm_struct_t *shm) { + int ret_code, i; + bitmap_t test_map; + int64_t sem_number, num_within_bitmap; + + if (shm == NULL) { + return -1 * EINVAL; + } + + // Lock the semaphore controlling access to our shared memory + ret_code = take_mutex(&(shm->segment_lock)); + if (ret_code != 0) { + return -1 * ret_code; + } + + // Loop through our bitmaps to search for one that is not full + for (i = 0; i < shm->num_bitmaps; i++) { + if (shm->locks[i].bitmap != 0xFFFFFFFF) { + test_map = 0x1; + num_within_bitmap = 0; + while (test_map != 0) { + if ((test_map & shm->locks[i].bitmap) == 0) { + // Compute the number of the semaphore we are allocating + sem_number = (BITMAP_SIZE * i) + num_within_bitmap; + // OR in the bitmap + shm->locks[i].bitmap = shm->locks[i].bitmap | test_map; + + // Clear the mutex + ret_code = release_mutex(&(shm->segment_lock)); + if (ret_code != 0) { + return -1 * ret_code; + } + + // Return the semaphore we've allocated + return sem_number; + } + test_map = test_map << 1; + num_within_bitmap++; + } + // We should never fall through this loop + // TODO maybe an assert() here to panic if we do? + } + } + + // Clear the mutex + ret_code = release_mutex(&(shm->segment_lock)); + if (ret_code != 0) { + return -1 * ret_code; + } + + // All bitmaps are full + // We have no available semaphores, report allocation failure + return -1 * ENOSPC; +} + +// Deallocate a given semaphore +// Returns 0 on success, negative ERRNO values on failure +int32_t deallocate_semaphore(shm_struct_t *shm, uint32_t sem_index) { + bitmap_t test_map; + int bitmap_index, index_in_bitmap, ret_code, i; + + if (shm == NULL) { + return -1 * EINVAL; + } + + // Check if the lock index is valid + if (sem_index >= shm->num_locks) { + return -1 * EINVAL; + } + + bitmap_index = sem_index / BITMAP_SIZE; + index_in_bitmap = sem_index % BITMAP_SIZE; + + // This should never happen if the sem_index test above succeeded, but better + // safe than sorry + if (bitmap_index >= shm->num_bitmaps) { + return -1 * EFAULT; + } + + test_map = 0x1 << index_in_bitmap; + + // Lock the mutex controlling access to our shared memory + ret_code = take_mutex(&(shm->segment_lock)); + if (ret_code != 0) { + return -1 * ret_code; + } + + // Check if the semaphore is allocated + if ((test_map & shm->locks[bitmap_index].bitmap) == 0) { + ret_code = release_mutex(&(shm->segment_lock)); + if (ret_code != 0) { + return -1 * ret_code; + } + + return -1 * ENOENT; + } + + // The semaphore is allocated, clear it + // Invert the bitmask we used to test to clear the bit + test_map = ~test_map; + shm->locks[bitmap_index].bitmap = shm->locks[bitmap_index].bitmap & test_map; + + ret_code = release_mutex(&(shm->segment_lock)); + if (ret_code != 0) { + return -1 * ret_code; + } + + return 0; +} + +// Lock a given semaphore +// Does not check if the semaphore is allocated - this ensures that, even for +// removed containers, we can still successfully lock to check status (and +// subsequently realize they have been removed). +// Returns 0 on success, -1 on failure +int32_t lock_semaphore(shm_struct_t *shm, uint32_t sem_index) { + int bitmap_index, index_in_bitmap, ret_code; + + if (shm == NULL) { + return -1 * EINVAL; + } + + if (sem_index >= shm->num_locks) { + return -1 * EINVAL; + } + + bitmap_index = sem_index / BITMAP_SIZE; + index_in_bitmap = sem_index % BITMAP_SIZE; + + return -1 * take_mutex(&(shm->locks[bitmap_index].locks[index_in_bitmap])); +} + +// Unlock a given semaphore +// Does not check if the semaphore is allocated - this ensures that, even for +// removed containers, we can still successfully lock to check status (and +// subsequently realize they have been removed). +// Returns 0 on success, -1 on failure +int32_t unlock_semaphore(shm_struct_t *shm, uint32_t sem_index) { + int bitmap_index, index_in_bitmap, ret_code; + + if (shm == NULL) { + return -1 * EINVAL; + } + + if (sem_index >= shm->num_locks) { + return -1 * EINVAL; + } + + bitmap_index = sem_index / BITMAP_SIZE; + index_in_bitmap = sem_index % BITMAP_SIZE; + + return -1 * release_mutex(&(shm->locks[bitmap_index].locks[index_in_bitmap])); +} diff --git a/libpod/lock/shm/shm_lock.go b/libpod/lock/shm/shm_lock.go new file mode 100644 index 000000000..87d28e5c1 --- /dev/null +++ b/libpod/lock/shm/shm_lock.go @@ -0,0 +1,216 @@ +package shm + +// #cgo LDFLAGS: -lrt -lpthread +// #include <stdlib.h> +// #include "shm_lock.h" +// const uint32_t bitmap_size_c = BITMAP_SIZE; +import "C" + +import ( + "runtime" + "syscall" + "unsafe" + + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +var ( + // BitmapSize is the size of the bitmap used when managing SHM locks. + // an SHM lock manager's max locks will be rounded up to a multiple of + // this number. + BitmapSize uint32 = uint32(C.bitmap_size_c) +) + +// SHMLocks is a struct enabling POSIX semaphore locking in a shared memory +// segment. +type SHMLocks struct { // nolint + lockStruct *C.shm_struct_t + maxLocks uint32 + valid bool +} + +// CreateSHMLock sets up a shared-memory segment holding a given number of POSIX +// semaphores, and returns a struct that can be used to operate on those locks. +// numLocks must not be 0, and may be rounded up to a multiple of the bitmap +// size used by the underlying implementation. +func CreateSHMLock(path string, numLocks uint32) (*SHMLocks, error) { + if numLocks == 0 { + return nil, errors.Wrapf(syscall.EINVAL, "number of locks must be greater than 0") + } + + locks := new(SHMLocks) + + cPath := C.CString(path) + defer C.free(unsafe.Pointer(cPath)) + + var errCode C.int + lockStruct := C.setup_lock_shm(cPath, C.uint32_t(numLocks), &errCode) + if lockStruct == nil { + // We got a null pointer, so something errored + return nil, errors.Wrapf(syscall.Errno(-1*errCode), "failed to create %d locks in %s", numLocks, path) + } + + locks.lockStruct = lockStruct + locks.maxLocks = uint32(lockStruct.num_locks) + locks.valid = true + + logrus.Debugf("Initialized SHM lock manager at path %s", path) + + return locks, nil +} + +// OpenSHMLock opens an existing shared-memory segment holding a given number of +// POSIX semaphores. numLocks must match the number of locks the shared memory +// segment was created with. +func OpenSHMLock(path string, numLocks uint32) (*SHMLocks, error) { + if numLocks == 0 { + return nil, errors.Wrapf(syscall.EINVAL, "number of locks must be greater than 0") + } + + locks := new(SHMLocks) + + cPath := C.CString(path) + defer C.free(unsafe.Pointer(cPath)) + + var errCode C.int + lockStruct := C.open_lock_shm(cPath, C.uint32_t(numLocks), &errCode) + if lockStruct == nil { + // We got a null pointer, so something errored + return nil, errors.Wrapf(syscall.Errno(-1*errCode), "failed to open %d locks in %s", numLocks, path) + } + + locks.lockStruct = lockStruct + locks.maxLocks = numLocks + locks.valid = true + + return locks, nil +} + +// GetMaxLocks returns the maximum number of locks in the SHM +func (locks *SHMLocks) GetMaxLocks() uint32 { + return locks.maxLocks +} + +// Close closes an existing shared-memory segment. +// The segment will be rendered unusable after closing. +// WARNING: If you Close() while there are still locks locked, these locks may +// fail to release, causing a program freeze. +// Close() is only intended to be used while testing the locks. +func (locks *SHMLocks) Close() error { + if !locks.valid { + return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + } + + locks.valid = false + + retCode := C.close_lock_shm(locks.lockStruct) + if retCode < 0 { + // Negative errno returned + return syscall.Errno(-1 * retCode) + } + + return nil +} + +// AllocateSemaphore allocates a semaphore from a shared-memory segment for use +// by a container or pod. +// Returns the index of the semaphore that was allocated. +// Allocations past the maximum number of locks given when the SHM segment was +// created will result in an error, and no semaphore will be allocated. +func (locks *SHMLocks) AllocateSemaphore() (uint32, error) { + if !locks.valid { + return 0, errors.Wrapf(syscall.EINVAL, "locks have already been closed") + } + + // This returns a U64, so we have the full u32 range available for + // semaphore indexes, and can still return error codes. + retCode := C.allocate_semaphore(locks.lockStruct) + if retCode < 0 { + // Negative errno returned + return 0, syscall.Errno(-1 * retCode) + } + + return uint32(retCode), nil +} + +// DeallocateSemaphore frees a semaphore in a shared-memory segment so it can be +// reallocated to another container or pod. +// The given semaphore must be already allocated, or an error will be returned. +func (locks *SHMLocks) DeallocateSemaphore(sem uint32) error { + if !locks.valid { + return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + } + + if sem > locks.maxLocks { + return errors.Wrapf(syscall.EINVAL, "given semaphore %d is higher than maximum locks count %d", sem, locks.maxLocks) + } + + retCode := C.deallocate_semaphore(locks.lockStruct, C.uint32_t(sem)) + if retCode < 0 { + // Negative errno returned + return syscall.Errno(-1 * retCode) + } + + return nil +} + +// LockSemaphore locks the given semaphore. +// If the semaphore is already locked, LockSemaphore will block until the lock +// can be acquired. +// There is no requirement that the given semaphore be allocated. +// This ensures that attempts to lock a container after it has been deleted, +// but before the caller has queried the database to determine this, will +// succeed. +func (locks *SHMLocks) LockSemaphore(sem uint32) error { + if !locks.valid { + return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + } + + if sem > locks.maxLocks { + return errors.Wrapf(syscall.EINVAL, "given semaphore %d is higher than maximum locks count %d", sem, locks.maxLocks) + } + + // For pthread mutexes, we have to guarantee lock and unlock happen in + // the same thread. + runtime.LockOSThread() + + retCode := C.lock_semaphore(locks.lockStruct, C.uint32_t(sem)) + if retCode < 0 { + // Negative errno returned + return syscall.Errno(-1 * retCode) + } + + return nil +} + +// UnlockSemaphore unlocks the given semaphore. +// Unlocking a semaphore that is already unlocked with return EBUSY. +// There is no requirement that the given semaphore be allocated. +// This ensures that attempts to lock a container after it has been deleted, +// but before the caller has queried the database to determine this, will +// succeed. +func (locks *SHMLocks) UnlockSemaphore(sem uint32) error { + if !locks.valid { + return errors.Wrapf(syscall.EINVAL, "locks have already been closed") + } + + if sem > locks.maxLocks { + return errors.Wrapf(syscall.EINVAL, "given semaphore %d is higher than maximum locks count %d", sem, locks.maxLocks) + } + + retCode := C.unlock_semaphore(locks.lockStruct, C.uint32_t(sem)) + if retCode < 0 { + // Negative errno returned + return syscall.Errno(-1 * retCode) + } + + // For pthread mutexes, we have to guarantee lock and unlock happen in + // the same thread. + // OK if we take multiple locks - UnlockOSThread() won't actually unlock + // until the number of calls equals the number of calls to + // LockOSThread() + runtime.UnlockOSThread() + + return nil +} diff --git a/libpod/lock/shm/shm_lock.h b/libpod/lock/shm/shm_lock.h new file mode 100644 index 000000000..8e7e23fb7 --- /dev/null +++ b/libpod/lock/shm/shm_lock.h @@ -0,0 +1,46 @@ +#ifndef shm_locks_h_ +#define shm_locks_h_ + +#include <pthread.h> +#include <stdint.h> + +// Magic number to ensure we open the right SHM segment +#define MAGIC 0x87D1 + +// Type for our bitmaps +typedef uint32_t bitmap_t; + +// bitmap size +#define BITMAP_SIZE (sizeof(bitmap_t) * 8) + +// Struct to hold a single bitmap and associated locks +typedef struct lock_group { + bitmap_t bitmap; + pthread_mutex_t locks[BITMAP_SIZE]; +} lock_group_t; + +// Struct to hold our SHM locks. +// Unused is required to be 0 in the current implementation. If we ever make +// changes to this structure in the future, this will be repurposed as a version +// field. +typedef struct shm_struct { + uint16_t magic; + uint16_t unused; + pthread_mutex_t segment_lock; + uint32_t num_bitmaps; + uint32_t num_locks; + lock_group_t locks[]; +} shm_struct_t; + +static size_t compute_shm_size(uint32_t num_bitmaps); +static int take_mutex(pthread_mutex_t *mutex); +static int release_mutex(pthread_mutex_t *mutex); +shm_struct_t *setup_lock_shm(char *path, uint32_t num_locks, int *error_code); +shm_struct_t *open_lock_shm(char *path, uint32_t num_locks, int *error_code); +int32_t close_lock_shm(shm_struct_t *shm); +int64_t allocate_semaphore(shm_struct_t *shm); +int32_t deallocate_semaphore(shm_struct_t *shm, uint32_t sem_index); +int32_t lock_semaphore(shm_struct_t *shm, uint32_t sem_index); +int32_t unlock_semaphore(shm_struct_t *shm, uint32_t sem_index); + +#endif diff --git a/libpod/lock/shm/shm_lock_test.go b/libpod/lock/shm/shm_lock_test.go new file mode 100644 index 000000000..594eb5d8e --- /dev/null +++ b/libpod/lock/shm/shm_lock_test.go @@ -0,0 +1,278 @@ +package shm + +import ( + "fmt" + "os" + "runtime" + "syscall" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// All tests here are in the same process, which somewhat limits their utility +// The big intent of this package it multiprocess locking, which is really hard +// to test without actually having multiple processes... +// We can at least verify that the locks work within the local process. + +var ( + // 4 * BITMAP_SIZE to ensure we have to traverse bitmaps + numLocks = 4 * BitmapSize +) + +const lockPath = "/libpod_test" + +// We need a test main to ensure that the SHM is created before the tests run +func TestMain(m *testing.M) { + shmLock, err := CreateSHMLock(lockPath, numLocks) + if err != nil { + fmt.Fprintf(os.Stderr, "Error creating SHM for tests: %v\n", err) + os.Exit(-1) + } + + // Close the SHM - every subsequent test will reopen + if err := shmLock.Close(); err != nil { + fmt.Fprintf(os.Stderr, "Error closing SHM locks: %v\n", err) + os.Exit(-1) + } + + exitCode := m.Run() + + // We need to remove the SHM segment to clean up after ourselves + os.RemoveAll("/dev/shm/libpod_lock") + + os.Exit(exitCode) +} + +func runLockTest(t *testing.T, testFunc func(*testing.T, *SHMLocks)) { + locks, err := OpenSHMLock(lockPath, numLocks) + if err != nil { + t.Fatalf("Error opening locks: %v", err) + } + defer func() { + // Deallocate all locks + // Ignore ENOENT (lock is not allocated) + var i uint32 + for i = 0; i < numLocks; i++ { + if err := locks.DeallocateSemaphore(i); err != nil && err != syscall.ENOENT { + t.Fatalf("Error deallocating semaphore %d: %v", i, err) + } + } + + if err := locks.Close(); err != nil { + t.Fatalf("Error closing locks: %v", err) + } + }() + + success := t.Run("locks", func(t *testing.T) { + testFunc(t, locks) + }) + if !success { + t.Fail() + } +} + +// Test that creating an SHM with a bad size rounds up to a good size +func TestCreateNewSHMBadSizeRoundsUp(t *testing.T) { + // Odd number, not a power of 2, should never be a word size on a system + lock, err := CreateSHMLock("/test1", 7) + assert.NoError(t, err) + + assert.Equal(t, lock.GetMaxLocks(), BitmapSize) + + if err := lock.Close(); err != nil { + t.Fatalf("Error closing locks: %v", err) + } +} + +// Test that creating an SHM with 0 size fails +func TestCreateNewSHMZeroSize(t *testing.T) { + _, err := CreateSHMLock("/test2", 0) + assert.Error(t, err) +} + +// Test that deallocating an unallocated lock errors +func TestDeallocateUnallocatedLockErrors(t *testing.T) { + runLockTest(t, func(t *testing.T, locks *SHMLocks) { + err := locks.DeallocateSemaphore(0) + assert.Error(t, err) + }) +} + +// Test that unlocking an unlocked lock fails +func TestUnlockingUnlockedLockFails(t *testing.T) { + runLockTest(t, func(t *testing.T, locks *SHMLocks) { + err := locks.UnlockSemaphore(0) + assert.Error(t, err) + }) +} + +// Test that locking and double-unlocking fails +func TestDoubleUnlockFails(t *testing.T) { + runLockTest(t, func(t *testing.T, locks *SHMLocks) { + err := locks.LockSemaphore(0) + assert.NoError(t, err) + + err = locks.UnlockSemaphore(0) + assert.NoError(t, err) + + err = locks.UnlockSemaphore(0) + assert.Error(t, err) + }) +} + +// Test allocating - lock - unlock - deallocate cycle, single lock +func TestLockLifecycleSingleLock(t *testing.T) { + runLockTest(t, func(t *testing.T, locks *SHMLocks) { + sem, err := locks.AllocateSemaphore() + require.NoError(t, err) + + err = locks.LockSemaphore(sem) + assert.NoError(t, err) + + err = locks.UnlockSemaphore(sem) + assert.NoError(t, err) + + err = locks.DeallocateSemaphore(sem) + assert.NoError(t, err) + }) +} + +// Test allocate two locks returns different locks +func TestAllocateTwoLocksGetsDifferentLocks(t *testing.T) { + runLockTest(t, func(t *testing.T, locks *SHMLocks) { + sem1, err := locks.AllocateSemaphore() + assert.NoError(t, err) + + sem2, err := locks.AllocateSemaphore() + assert.NoError(t, err) + + assert.NotEqual(t, sem1, sem2) + }) +} + +// Test allocate all locks successful and all are unique +func TestAllocateAllLocksSucceeds(t *testing.T) { + runLockTest(t, func(t *testing.T, locks *SHMLocks) { + sems := make(map[uint32]bool) + var i uint32 + for i = 0; i < numLocks; i++ { + sem, err := locks.AllocateSemaphore() + assert.NoError(t, err) + + // Ensure the allocate semaphore is unique + _, ok := sems[sem] + assert.False(t, ok) + + sems[sem] = true + } + }) +} + +// Test allocating more than the given max fails +func TestAllocateTooManyLocksFails(t *testing.T) { + runLockTest(t, func(t *testing.T, locks *SHMLocks) { + // Allocate all locks + var i uint32 + for i = 0; i < numLocks; i++ { + _, err := locks.AllocateSemaphore() + assert.NoError(t, err) + } + + // Try and allocate one more + _, err := locks.AllocateSemaphore() + assert.Error(t, err) + }) +} + +// Test allocating max locks, deallocating one, and then allocating again succeeds +func TestAllocateDeallocateCycle(t *testing.T) { + runLockTest(t, func(t *testing.T, locks *SHMLocks) { + // Allocate all locks + var i uint32 + for i = 0; i < numLocks; i++ { + _, err := locks.AllocateSemaphore() + assert.NoError(t, err) + } + + // Now loop through again, deallocating and reallocating. + // Each time we free 1 semaphore, allocate again, and make sure + // we get the same semaphore back. + var j uint32 + for j = 0; j < numLocks; j++ { + err := locks.DeallocateSemaphore(j) + assert.NoError(t, err) + + newSem, err := locks.AllocateSemaphore() + assert.NoError(t, err) + assert.Equal(t, j, newSem) + } + }) +} + +// Test that locks actually lock +func TestLockSemaphoreActuallyLocks(t *testing.T) { + runLockTest(t, func(t *testing.T, locks *SHMLocks) { + // This entire test is very ugly - lots of sleeps to try and get + // things to occur in the right order. + // It also doesn't even exercise the multiprocess nature of the + // locks. + + // Get the current time + startTime := time.Now() + + // Start a goroutine to take the lock and then release it after + // a second. + go func() { + err := locks.LockSemaphore(0) + assert.NoError(t, err) + + time.Sleep(1 * time.Second) + + err = locks.UnlockSemaphore(0) + assert.NoError(t, err) + }() + + // Sleep for a quarter of a second to give the goroutine time + // to kick off and grab the lock + time.Sleep(250 * time.Millisecond) + + // Take the lock + err := locks.LockSemaphore(0) + assert.NoError(t, err) + + // Get the current time + endTime := time.Now() + + // Verify that at least 1 second has passed since start + duration := endTime.Sub(startTime) + assert.True(t, duration.Seconds() > 1.0) + }) +} + +// Test that locking and unlocking two semaphores succeeds +// Ensures that runtime.LockOSThread() is doing its job +func TestLockAndUnlockTwoSemaphore(t *testing.T) { + runLockTest(t, func(t *testing.T, locks *SHMLocks) { + err := locks.LockSemaphore(5) + assert.NoError(t, err) + + err = locks.LockSemaphore(6) + assert.NoError(t, err) + + err = locks.UnlockSemaphore(6) + assert.NoError(t, err) + + // Now yield scheduling + // To try and get us on another OS thread + runtime.Gosched() + + // And unlock the last semaphore + // If we are in a different OS thread, this should fail. + // However, runtime.UnlockOSThread() should guarantee we are not + err = locks.UnlockSemaphore(5) + assert.NoError(t, err) + }) +} diff --git a/libpod/lock/shm_lock_manager_linux.go b/libpod/lock/shm_lock_manager_linux.go new file mode 100644 index 000000000..94dfd7dd7 --- /dev/null +++ b/libpod/lock/shm_lock_manager_linux.go @@ -0,0 +1,102 @@ +// +build linux + +package lock + +import ( + "syscall" + + "github.com/containers/libpod/libpod/lock/shm" + "github.com/pkg/errors" +) + +// SHMLockManager manages shared memory locks. +type SHMLockManager struct { + locks *shm.SHMLocks +} + +// NewSHMLockManager makes a new SHMLockManager with the given number of locks. +// Due to the underlying implementation, the exact number of locks created may +// be greater than the number given here. +func NewSHMLockManager(path string, numLocks uint32) (Manager, error) { + locks, err := shm.CreateSHMLock(path, numLocks) + if err != nil { + return nil, err + } + + manager := new(SHMLockManager) + manager.locks = locks + + return manager, nil +} + +// OpenSHMLockManager opens an existing SHMLockManager with the given number of +// locks. +func OpenSHMLockManager(path string, numLocks uint32) (Manager, error) { + locks, err := shm.OpenSHMLock(path, numLocks) + if err != nil { + return nil, err + } + + manager := new(SHMLockManager) + manager.locks = locks + + return manager, nil +} + +// AllocateLock allocates a new lock from the manager. +func (m *SHMLockManager) AllocateLock() (Locker, error) { + semIndex, err := m.locks.AllocateSemaphore() + if err != nil { + return nil, err + } + + lock := new(SHMLock) + lock.lockID = semIndex + lock.manager = m + + return lock, nil +} + +// RetrieveLock retrieves a lock from the manager given its ID. +func (m *SHMLockManager) RetrieveLock(id uint32) (Locker, error) { + lock := new(SHMLock) + lock.lockID = id + lock.manager = m + + if id >= m.locks.GetMaxLocks() { + return nil, errors.Wrapf(syscall.EINVAL, "lock ID %d is too large - max lock size is %d", + id, m.locks.GetMaxLocks()-1) + } + + return lock, nil +} + +// SHMLock is an individual shared memory lock. +type SHMLock struct { + lockID uint32 + manager *SHMLockManager +} + +// ID returns the ID of the lock. +func (l *SHMLock) ID() uint32 { + return l.lockID +} + +// Lock acquires the lock. +func (l *SHMLock) Lock() { + if err := l.manager.locks.LockSemaphore(l.lockID); err != nil { + panic(err.Error()) + } +} + +// Unlock releases the lock. +func (l *SHMLock) Unlock() { + if err := l.manager.locks.UnlockSemaphore(l.lockID); err != nil { + panic(err.Error()) + } +} + +// Free releases the lock, allowing it to be reused. +func (l *SHMLock) Free() error { + return l.manager.locks.DeallocateSemaphore(l.lockID) +} diff --git a/libpod/lock/shm_lock_manager_unsupported.go b/libpod/lock/shm_lock_manager_unsupported.go new file mode 100644 index 000000000..cbdb2f7bc --- /dev/null +++ b/libpod/lock/shm_lock_manager_unsupported.go @@ -0,0 +1,29 @@ +// +build !linux + +package lock + +import "fmt" + +// SHMLockManager is a shared memory lock manager. +// It is not supported on non-Unix platforms. +type SHMLockManager struct{} + +// NewSHMLockManager is not supported on this platform +func NewSHMLockManager(path string, numLocks uint32) (Manager, error) { + return nil, fmt.Errorf("not supported") +} + +// OpenSHMLockManager is not supported on this platform +func OpenSHMLockManager(path string, numLocks uint32) (Manager, error) { + return nil, fmt.Errorf("not supported") +} + +// AllocateLock is not supported on this platform +func (m *SHMLockManager) AllocateLock() (Locker, error) { + return nil, fmt.Errorf("not supported") +} + +// RetrieveLock is not supported on this platform +func (m *SHMLockManager) RetrieveLock(id string) (Locker, error) { + return nil, fmt.Errorf("not supported") +} diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 43d0a61a4..f9caf26d1 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -50,7 +50,16 @@ func (r *Runtime) getPodNetwork(id, name, nsPath string, networks []string, port // Create and configure a new network namespace for a container func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Result, error) { - podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctrNS.Path(), ctr.config.Networks, ctr.config.PortMappings, ctr.config.StaticIP) + var requestedIP net.IP + if ctr.requestedIP != nil { + requestedIP = ctr.requestedIP + // cancel request for a specific IP in case the container is reused later + ctr.requestedIP = nil + } else { + requestedIP = ctr.config.StaticIP + } + + podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctrNS.Path(), ctr.config.Networks, ctr.config.PortMappings, requestedIP) results, err := r.netPlugin.SetUpPod(podNetwork) if err != nil { @@ -112,6 +121,19 @@ func (r *Runtime) createNetNS(ctr *Container) (n ns.NetNS, q []*cnitypes.Result, return ctrNS, networkStatus, err } +type slirp4netnsCmdArg struct { + Proto string `json:"proto,omitempty"` + HostAddr string `json:"host_addr"` + HostPort int32 `json:"host_port"` + GuestAddr string `json:"guest_addr"` + GuestPort int32 `json:"guest_port"` +} + +type slirp4netnsCmd struct { + Execute string `json:"execute"` + Args slirp4netnsCmdArg `json:"arguments"` +} + // Configure the network namespace for a rootless container func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) { defer ctr.rootlessSlirpSyncR.Close() @@ -130,7 +152,15 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) { defer syncR.Close() defer syncW.Close() - cmd := exec.Command(path, "-c", "-e", "3", "-r", "4", fmt.Sprintf("%d", ctr.state.PID), "tap0") + havePortMapping := len(ctr.Config().PortMappings) > 0 + apiSocket := filepath.Join(r.ociRuntime.tmpDir, fmt.Sprintf("%s.net", ctr.config.ID)) + var cmd *exec.Cmd + if havePortMapping { + // if we need ports to be mapped from the host, create a API socket to use for communicating with slirp4netns. + cmd = exec.Command(path, "-c", "-e", "3", "-r", "4", "--api-socket", apiSocket, fmt.Sprintf("%d", ctr.state.PID), "tap0") + } else { + cmd = exec.Command(path, "-c", "-e", "3", "-r", "4", fmt.Sprintf("%d", ctr.state.PID), "tap0") + } cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, @@ -153,19 +183,99 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) { if os.IsTimeout(err) { // Check if the process is still running. var status syscall.WaitStatus - _, err := syscall.Wait4(cmd.Process.Pid, &status, syscall.WNOHANG, nil) + pid, err := syscall.Wait4(cmd.Process.Pid, &status, syscall.WNOHANG, nil) if err != nil { return errors.Wrapf(err, "failed to read slirp4netns process status") } + if pid != cmd.Process.Pid { + continue + } if status.Exited() || status.Signaled() { return errors.New("slirp4netns failed") } - continue } return errors.Wrapf(err, "failed to read from slirp4netns sync pipe") } } + + if havePortMapping { + const pidWaitTimeout = 60 * time.Second + chWait := make(chan error) + go func() { + interval := 25 * time.Millisecond + for i := time.Duration(0); i < pidWaitTimeout; i += interval { + // Check if the process is still running. + var status syscall.WaitStatus + pid, err := syscall.Wait4(cmd.Process.Pid, &status, syscall.WNOHANG, nil) + if err != nil { + break + } + if pid != cmd.Process.Pid { + continue + } + if status.Exited() || status.Signaled() { + chWait <- fmt.Errorf("slirp4netns exited with status %d", status.ExitStatus()) + } + time.Sleep(interval) + } + }() + defer close(chWait) + + // wait that API socket file appears before trying to use it. + if _, err := WaitForFile(apiSocket, chWait, pidWaitTimeout*time.Millisecond); err != nil { + return errors.Wrapf(err, "waiting for slirp4nets to create the api socket file %s", apiSocket) + } + + // for each port we want to add we need to open a connection to the slirp4netns control socket + // and send the add_hostfwd command. + for _, i := range ctr.config.PortMappings { + conn, err := net.Dial("unix", apiSocket) + if err != nil { + return errors.Wrapf(err, "cannot open connection to %s", apiSocket) + } + defer conn.Close() + hostIP := i.HostIP + if hostIP == "" { + hostIP = "0.0.0.0" + } + cmd := slirp4netnsCmd{ + Execute: "add_hostfwd", + Args: slirp4netnsCmdArg{ + Proto: i.Protocol, + HostAddr: hostIP, + HostPort: i.HostPort, + GuestPort: i.ContainerPort, + }, + } + // create the JSON payload and send it. Mark the end of request shutting down writes + // to the socket, as requested by slirp4netns. + data, err := json.Marshal(&cmd) + if err != nil { + return errors.Wrapf(err, "cannot marshal JSON for slirp4netns") + } + if _, err := conn.Write([]byte(fmt.Sprintf("%s\n", data))); err != nil { + return errors.Wrapf(err, "cannot write to control socket %s", apiSocket) + } + if err := conn.(*net.UnixConn).CloseWrite(); err != nil { + return errors.Wrapf(err, "cannot shutdown the socket %s", apiSocket) + } + buf := make([]byte, 2048) + len, err := conn.Read(buf) + if err != nil { + return errors.Wrapf(err, "cannot read from control socket %s", apiSocket) + } + // if there is no 'error' key in the received JSON data, then the operation was + // successful. + var y map[string]interface{} + if err := json.Unmarshal(buf[0:len], &y); err != nil { + return errors.Wrapf(err, "error parsing error status from slirp4netns") + } + if e, found := y["error"]; found { + return errors.Errorf("error from slirp4netns while setting up port redirection: %v", e) + } + } + } return nil } @@ -258,7 +368,16 @@ func (r *Runtime) teardownNetNS(ctr *Container) error { logrus.Debugf("Tearing down network namespace at %s for container %s", ctr.state.NetNS.Path(), ctr.ID()) - podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), ctr.config.Networks, ctr.config.PortMappings, ctr.config.StaticIP) + var requestedIP net.IP + if ctr.requestedIP != nil { + requestedIP = ctr.requestedIP + // cancel request for a specific IP in case the container is reused later + ctr.requestedIP = nil + } else { + requestedIP = ctr.config.StaticIP + } + + podNetwork := r.getPodNetwork(ctr.ID(), ctr.Name(), ctr.state.NetNS.Path(), ctr.config.Networks, ctr.config.PortMappings, requestedIP) // The network may have already been torn down, so don't fail here, just log if err := r.netPlugin.TearDownPod(podNetwork); err != nil { diff --git a/libpod/oci.go b/libpod/oci.go index 093bfdd35..e55bd57dc 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -3,7 +3,6 @@ package libpod import ( "bufio" "bytes" - "encoding/json" "fmt" "io/ioutil" "net" @@ -76,10 +75,10 @@ type syncInfo struct { } // Make a new OCI runtime with provided options -func newOCIRuntime(name string, path string, conmonPath string, conmonEnv []string, cgroupManager string, tmpDir string, logSizeMax int64, noPivotRoot bool, reservePorts bool) (*OCIRuntime, error) { +func newOCIRuntime(oruntime OCIRuntimePath, conmonPath string, conmonEnv []string, cgroupManager string, tmpDir string, logSizeMax int64, noPivotRoot bool, reservePorts bool) (*OCIRuntime, error) { runtime := new(OCIRuntime) - runtime.name = name - runtime.path = path + runtime.name = oruntime.Name + runtime.path = oruntime.Paths[0] runtime.conmonPath = conmonPath runtime.conmonEnv = conmonEnv runtime.cgroupManager = cgroupManager @@ -324,7 +323,7 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res cmd.Env = append(cmd.Env, fmt.Sprintf("HOME=%s", os.Getenv("HOME"))) cmd.Env = append(cmd.Env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)) - if r.reservePorts { + if r.reservePorts && !ctr.config.NetMode.IsSlirp4netns() { ports, err := bindPorts(ctr.config.PortMappings) if err != nil { return err @@ -357,18 +356,25 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res // Set the label of the conmon process to be level :s0 // This will allow the container processes to talk to fifo-files // passed into the container by conmon - var plabel string + var ( + plabel string + con selinux.Context + ) plabel, err = selinux.CurrentLabel() if err != nil { childPipe.Close() return errors.Wrapf(err, "Failed to get current SELinux label") } - c := selinux.NewContext(plabel) + con, err = selinux.NewContext(plabel) + if err != nil { + return errors.Wrapf(err, "Failed to get new context from SELinux label") + } + runtime.LockOSThread() - if c["level"] != "s0" && c["level"] != "" { - c["level"] = "s0" - if err = label.SetProcessLabel(c.Get()); err != nil { + if con["level"] != "s0" && con["level"] != "" { + con["level"] = "s0" + if err = label.SetProcessLabel(con.Get()); err != nil { runtime.UnlockOSThread() return err } @@ -728,7 +734,7 @@ func (r *OCIRuntime) unpauseContainer(ctr *Container) error { // TODO: Add --detach support // TODO: Convert to use conmon // TODO: add --pid-file and use that to generate exec session tracking -func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, user, sessionID string) (*exec.Cmd, error) { +func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, cwd, user, sessionID string) (*exec.Cmd, error) { if len(cmd) == 0 { return nil, errors.Wrapf(ErrInvalidArg, "must provide a command to execute") } @@ -749,7 +755,9 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty args = append(args, "exec") - args = append(args, "--cwd", c.config.Spec.Process.Cwd) + if cwd != "" { + args = append(args, "--cwd", cwd) + } args = append(args, "--pid-file", c.execPidPath(sessionID)) diff --git a/libpod/options.go b/libpod/options.go index 319e1f6c6..d965c058e 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -137,17 +137,17 @@ func WithStateType(storeType RuntimeStateStore) RuntimeOption { } // WithOCIRuntime specifies an OCI runtime to use for running containers. -func WithOCIRuntime(runtimePath string) RuntimeOption { +func WithOCIRuntime(runtime string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { return ErrRuntimeFinalized } - if runtimePath == "" { + if runtime == "" { return errors.Wrapf(ErrInvalidArg, "must provide a valid path") } - rt.config.RuntimePath = []string{runtimePath} + rt.config.OCIRuntime = runtime return nil } diff --git a/libpod/pod.go b/libpod/pod.go index 07f41f5c6..4ce697402 100644 --- a/libpod/pod.go +++ b/libpod/pod.go @@ -3,7 +3,7 @@ package libpod import ( "time" - "github.com/containers/storage" + "github.com/containers/libpod/libpod/lock" "github.com/cri-o/ocicni/pkg/ocicni" "github.com/pkg/errors" ) @@ -26,7 +26,7 @@ type Pod struct { valid bool runtime *Runtime - lock storage.Locker + lock lock.Locker } // PodConfig represents a pod's static configuration @@ -60,6 +60,9 @@ type PodConfig struct { // Time pod was created CreatedTime time.Time `json:"created"` + + // ID of the pod's lock + LockID uint32 `json:"lockID"` } // podState represents a pod's state diff --git a/libpod/pod_easyjson.go b/libpod/pod_easyjson.go deleted file mode 100644 index 8ea9a5e72..000000000 --- a/libpod/pod_easyjson.go +++ /dev/null @@ -1,877 +0,0 @@ -// +build seccomp ostree selinux varlink exclude_graphdriver_devicemapper - -// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. - -package libpod - -import ( - json "encoding/json" - ocicni "github.com/cri-o/ocicni/pkg/ocicni" - easyjson "github.com/mailru/easyjson" - jlexer "github.com/mailru/easyjson/jlexer" - jwriter "github.com/mailru/easyjson/jwriter" -) - -// suppress unused package warning -var ( - _ *json.RawMessage - _ *jlexer.Lexer - _ *jwriter.Writer - _ easyjson.Marshaler -) - -func easyjsonBe091417DecodeGithubComContainersLibpodLibpod(in *jlexer.Lexer, out *podState) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "cgroupPath": - out.CgroupPath = string(in.String()) - case "InfraContainerID": - out.InfraContainerID = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjsonBe091417EncodeGithubComContainersLibpodLibpod(out *jwriter.Writer, in podState) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"cgroupPath\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.CgroupPath)) - } - { - const prefix string = ",\"InfraContainerID\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.InfraContainerID)) - } - out.RawByte('}') -} - -// MarshalJSON supports json.Marshaler interface -func (v podState) MarshalJSON() ([]byte, error) { - w := jwriter.Writer{} - easyjsonBe091417EncodeGithubComContainersLibpodLibpod(&w, v) - return w.Buffer.BuildBytes(), w.Error -} - -// MarshalEasyJSON supports easyjson.Marshaler interface -func (v podState) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonBe091417EncodeGithubComContainersLibpodLibpod(w, v) -} - -// UnmarshalJSON supports json.Unmarshaler interface -func (v *podState) UnmarshalJSON(data []byte) error { - r := jlexer.Lexer{Data: data} - easyjsonBe091417DecodeGithubComContainersLibpodLibpod(&r, v) - return r.Error() -} - -// UnmarshalEasyJSON supports easyjson.Unmarshaler interface -func (v *podState) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonBe091417DecodeGithubComContainersLibpodLibpod(l, v) -} -func easyjsonBe091417DecodeGithubComContainersLibpodLibpod1(in *jlexer.Lexer, out *PodInspectState) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "cgroupPath": - out.CgroupPath = string(in.String()) - case "infraContainerID": - out.InfraContainerID = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjsonBe091417EncodeGithubComContainersLibpodLibpod1(out *jwriter.Writer, in PodInspectState) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"cgroupPath\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.CgroupPath)) - } - { - const prefix string = ",\"infraContainerID\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.InfraContainerID)) - } - out.RawByte('}') -} - -// MarshalJSON supports json.Marshaler interface -func (v PodInspectState) MarshalJSON() ([]byte, error) { - w := jwriter.Writer{} - easyjsonBe091417EncodeGithubComContainersLibpodLibpod1(&w, v) - return w.Buffer.BuildBytes(), w.Error -} - -// MarshalEasyJSON supports easyjson.Marshaler interface -func (v PodInspectState) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonBe091417EncodeGithubComContainersLibpodLibpod1(w, v) -} - -// UnmarshalJSON supports json.Unmarshaler interface -func (v *PodInspectState) UnmarshalJSON(data []byte) error { - r := jlexer.Lexer{Data: data} - easyjsonBe091417DecodeGithubComContainersLibpodLibpod1(&r, v) - return r.Error() -} - -// UnmarshalEasyJSON supports easyjson.Unmarshaler interface -func (v *PodInspectState) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonBe091417DecodeGithubComContainersLibpodLibpod1(l, v) -} -func easyjsonBe091417DecodeGithubComContainersLibpodLibpod2(in *jlexer.Lexer, out *PodInspect) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "Config": - if in.IsNull() { - in.Skip() - out.Config = nil - } else { - if out.Config == nil { - out.Config = new(PodConfig) - } - if data := in.Raw(); in.Ok() { - in.AddError((*out.Config).UnmarshalJSON(data)) - } - } - case "State": - if in.IsNull() { - in.Skip() - out.State = nil - } else { - if out.State == nil { - out.State = new(PodInspectState) - } - if data := in.Raw(); in.Ok() { - in.AddError((*out.State).UnmarshalJSON(data)) - } - } - case "Containers": - if in.IsNull() { - in.Skip() - out.Containers = nil - } else { - in.Delim('[') - if out.Containers == nil { - if !in.IsDelim(']') { - out.Containers = make([]PodContainerInfo, 0, 2) - } else { - out.Containers = []PodContainerInfo{} - } - } else { - out.Containers = (out.Containers)[:0] - } - for !in.IsDelim(']') { - var v1 PodContainerInfo - if data := in.Raw(); in.Ok() { - in.AddError((v1).UnmarshalJSON(data)) - } - out.Containers = append(out.Containers, v1) - in.WantComma() - } - in.Delim(']') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjsonBe091417EncodeGithubComContainersLibpodLibpod2(out *jwriter.Writer, in PodInspect) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"Config\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.Config == nil { - out.RawString("null") - } else { - out.Raw((*in.Config).MarshalJSON()) - } - } - { - const prefix string = ",\"State\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.State == nil { - out.RawString("null") - } else { - out.Raw((*in.State).MarshalJSON()) - } - } - { - const prefix string = ",\"Containers\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.Containers == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { - out.RawString("null") - } else { - out.RawByte('[') - for v2, v3 := range in.Containers { - if v2 > 0 { - out.RawByte(',') - } - out.Raw((v3).MarshalJSON()) - } - out.RawByte(']') - } - } - out.RawByte('}') -} - -// MarshalJSON supports json.Marshaler interface -func (v PodInspect) MarshalJSON() ([]byte, error) { - w := jwriter.Writer{} - easyjsonBe091417EncodeGithubComContainersLibpodLibpod2(&w, v) - return w.Buffer.BuildBytes(), w.Error -} - -// MarshalEasyJSON supports easyjson.Marshaler interface -func (v PodInspect) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonBe091417EncodeGithubComContainersLibpodLibpod2(w, v) -} - -// UnmarshalJSON supports json.Unmarshaler interface -func (v *PodInspect) UnmarshalJSON(data []byte) error { - r := jlexer.Lexer{Data: data} - easyjsonBe091417DecodeGithubComContainersLibpodLibpod2(&r, v) - return r.Error() -} - -// UnmarshalEasyJSON supports easyjson.Unmarshaler interface -func (v *PodInspect) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonBe091417DecodeGithubComContainersLibpodLibpod2(l, v) -} -func easyjsonBe091417DecodeGithubComContainersLibpodLibpod3(in *jlexer.Lexer, out *PodContainerInfo) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "id": - out.ID = string(in.String()) - case "state": - out.State = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjsonBe091417EncodeGithubComContainersLibpodLibpod3(out *jwriter.Writer, in PodContainerInfo) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"id\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.ID)) - } - { - const prefix string = ",\"state\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.State)) - } - out.RawByte('}') -} - -// MarshalJSON supports json.Marshaler interface -func (v PodContainerInfo) MarshalJSON() ([]byte, error) { - w := jwriter.Writer{} - easyjsonBe091417EncodeGithubComContainersLibpodLibpod3(&w, v) - return w.Buffer.BuildBytes(), w.Error -} - -// MarshalEasyJSON supports easyjson.Marshaler interface -func (v PodContainerInfo) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonBe091417EncodeGithubComContainersLibpodLibpod3(w, v) -} - -// UnmarshalJSON supports json.Unmarshaler interface -func (v *PodContainerInfo) UnmarshalJSON(data []byte) error { - r := jlexer.Lexer{Data: data} - easyjsonBe091417DecodeGithubComContainersLibpodLibpod3(&r, v) - return r.Error() -} - -// UnmarshalEasyJSON supports easyjson.Unmarshaler interface -func (v *PodContainerInfo) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonBe091417DecodeGithubComContainersLibpodLibpod3(l, v) -} -func easyjsonBe091417DecodeGithubComContainersLibpodLibpod4(in *jlexer.Lexer, out *PodConfig) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "id": - out.ID = string(in.String()) - case "name": - out.Name = string(in.String()) - case "namespace": - out.Namespace = string(in.String()) - case "labels": - if in.IsNull() { - in.Skip() - } else { - in.Delim('{') - if !in.IsDelim('}') { - out.Labels = make(map[string]string) - } else { - out.Labels = nil - } - for !in.IsDelim('}') { - key := string(in.String()) - in.WantColon() - var v4 string - v4 = string(in.String()) - (out.Labels)[key] = v4 - in.WantComma() - } - in.Delim('}') - } - case "cgroupParent": - out.CgroupParent = string(in.String()) - case "sharesCgroup": - out.UsePodCgroup = bool(in.Bool()) - case "sharesPid": - out.UsePodPID = bool(in.Bool()) - case "sharesIpc": - out.UsePodIPC = bool(in.Bool()) - case "sharesNet": - out.UsePodNet = bool(in.Bool()) - case "sharesMnt": - out.UsePodMount = bool(in.Bool()) - case "sharesUser": - out.UsePodUser = bool(in.Bool()) - case "sharesUts": - out.UsePodUTS = bool(in.Bool()) - case "infraConfig": - if in.IsNull() { - in.Skip() - out.InfraContainer = nil - } else { - if out.InfraContainer == nil { - out.InfraContainer = new(InfraContainerConfig) - } - easyjsonBe091417DecodeGithubComContainersLibpodLibpod5(in, &*out.InfraContainer) - } - case "created": - if data := in.Raw(); in.Ok() { - in.AddError((out.CreatedTime).UnmarshalJSON(data)) - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjsonBe091417EncodeGithubComContainersLibpodLibpod4(out *jwriter.Writer, in PodConfig) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"id\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.ID)) - } - { - const prefix string = ",\"name\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Name)) - } - if in.Namespace != "" { - const prefix string = ",\"namespace\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Namespace)) - } - { - const prefix string = ",\"labels\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.Labels == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 { - out.RawString(`null`) - } else { - out.RawByte('{') - v5First := true - for v5Name, v5Value := range in.Labels { - if v5First { - v5First = false - } else { - out.RawByte(',') - } - out.String(string(v5Name)) - out.RawByte(':') - out.String(string(v5Value)) - } - out.RawByte('}') - } - } - { - const prefix string = ",\"cgroupParent\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.CgroupParent)) - } - if in.UsePodCgroup { - const prefix string = ",\"sharesCgroup\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.UsePodCgroup)) - } - if in.UsePodPID { - const prefix string = ",\"sharesPid\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.UsePodPID)) - } - if in.UsePodIPC { - const prefix string = ",\"sharesIpc\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.UsePodIPC)) - } - if in.UsePodNet { - const prefix string = ",\"sharesNet\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.UsePodNet)) - } - if in.UsePodMount { - const prefix string = ",\"sharesMnt\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.UsePodMount)) - } - if in.UsePodUser { - const prefix string = ",\"sharesUser\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.UsePodUser)) - } - if in.UsePodUTS { - const prefix string = ",\"sharesUts\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.UsePodUTS)) - } - { - const prefix string = ",\"infraConfig\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.InfraContainer == nil { - out.RawString("null") - } else { - easyjsonBe091417EncodeGithubComContainersLibpodLibpod5(out, *in.InfraContainer) - } - } - { - const prefix string = ",\"created\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Raw((in.CreatedTime).MarshalJSON()) - } - out.RawByte('}') -} - -// MarshalJSON supports json.Marshaler interface -func (v PodConfig) MarshalJSON() ([]byte, error) { - w := jwriter.Writer{} - easyjsonBe091417EncodeGithubComContainersLibpodLibpod4(&w, v) - return w.Buffer.BuildBytes(), w.Error -} - -// MarshalEasyJSON supports easyjson.Marshaler interface -func (v PodConfig) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonBe091417EncodeGithubComContainersLibpodLibpod4(w, v) -} - -// UnmarshalJSON supports json.Unmarshaler interface -func (v *PodConfig) UnmarshalJSON(data []byte) error { - r := jlexer.Lexer{Data: data} - easyjsonBe091417DecodeGithubComContainersLibpodLibpod4(&r, v) - return r.Error() -} - -// UnmarshalEasyJSON supports easyjson.Unmarshaler interface -func (v *PodConfig) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonBe091417DecodeGithubComContainersLibpodLibpod4(l, v) -} -func easyjsonBe091417DecodeGithubComContainersLibpodLibpod5(in *jlexer.Lexer, out *InfraContainerConfig) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "makeInfraContainer": - out.HasInfraContainer = bool(in.Bool()) - case "infraPortBindings": - if in.IsNull() { - in.Skip() - out.PortBindings = nil - } else { - in.Delim('[') - if out.PortBindings == nil { - if !in.IsDelim(']') { - out.PortBindings = make([]ocicni.PortMapping, 0, 1) - } else { - out.PortBindings = []ocicni.PortMapping{} - } - } else { - out.PortBindings = (out.PortBindings)[:0] - } - for !in.IsDelim(']') { - var v6 ocicni.PortMapping - easyjsonBe091417DecodeGithubComContainersLibpodVendorGithubComCriOOcicniPkgOcicni(in, &v6) - out.PortBindings = append(out.PortBindings, v6) - in.WantComma() - } - in.Delim(']') - } - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjsonBe091417EncodeGithubComContainersLibpodLibpod5(out *jwriter.Writer, in InfraContainerConfig) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"makeInfraContainer\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Bool(bool(in.HasInfraContainer)) - } - { - const prefix string = ",\"infraPortBindings\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - if in.PortBindings == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { - out.RawString("null") - } else { - out.RawByte('[') - for v7, v8 := range in.PortBindings { - if v7 > 0 { - out.RawByte(',') - } - easyjsonBe091417EncodeGithubComContainersLibpodVendorGithubComCriOOcicniPkgOcicni(out, v8) - } - out.RawByte(']') - } - } - out.RawByte('}') -} -func easyjsonBe091417DecodeGithubComContainersLibpodVendorGithubComCriOOcicniPkgOcicni(in *jlexer.Lexer, out *ocicni.PortMapping) { - isTopLevel := in.IsStart() - if in.IsNull() { - if isTopLevel { - in.Consumed() - } - in.Skip() - return - } - in.Delim('{') - for !in.IsDelim('}') { - key := in.UnsafeString() - in.WantColon() - if in.IsNull() { - in.Skip() - in.WantComma() - continue - } - switch key { - case "hostPort": - out.HostPort = int32(in.Int32()) - case "containerPort": - out.ContainerPort = int32(in.Int32()) - case "protocol": - out.Protocol = string(in.String()) - case "hostIP": - out.HostIP = string(in.String()) - default: - in.SkipRecursive() - } - in.WantComma() - } - in.Delim('}') - if isTopLevel { - in.Consumed() - } -} -func easyjsonBe091417EncodeGithubComContainersLibpodVendorGithubComCriOOcicniPkgOcicni(out *jwriter.Writer, in ocicni.PortMapping) { - out.RawByte('{') - first := true - _ = first - { - const prefix string = ",\"hostPort\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int32(int32(in.HostPort)) - } - { - const prefix string = ",\"containerPort\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.Int32(int32(in.ContainerPort)) - } - { - const prefix string = ",\"protocol\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.Protocol)) - } - { - const prefix string = ",\"hostIP\":" - if first { - first = false - out.RawString(prefix[1:]) - } else { - out.RawString(prefix) - } - out.String(string(in.HostIP)) - } - out.RawByte('}') -} diff --git a/libpod/pod_internal.go b/libpod/pod_internal.go index 39a25c004..0f1f115e8 100644 --- a/libpod/pod_internal.go +++ b/libpod/pod_internal.go @@ -7,14 +7,13 @@ import ( "strings" "time" - "github.com/containers/storage" "github.com/containers/storage/pkg/stringid" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) // Creates a new, empty pod -func newPod(lockDir string, runtime *Runtime) (*Pod, error) { +func newPod(runtime *Runtime) (*Pod, error) { pod := new(Pod) pod.config = new(PodConfig) pod.config.ID = stringid.GenerateNonCryptoID() @@ -24,15 +23,6 @@ func newPod(lockDir string, runtime *Runtime) (*Pod, error) { pod.state = new(podState) pod.runtime = runtime - // Path our lock file will reside at - lockPath := filepath.Join(lockDir, pod.config.ID) - // Grab a lockfile at the given path - lock, err := storage.GetLockfile(lockPath) - if err != nil { - return nil, errors.Wrapf(err, "error creating lockfile for new pod") - } - pod.lock = lock - return pod, nil } @@ -55,6 +45,8 @@ func (p *Pod) save() error { } // Refresh a pod's state after restart +// This cannot lock any other pod, but may lock individual containers, as those +// will have refreshed by the time pod refresh runs. func (p *Pod) refresh() error { // Need to to an update from the DB to pull potentially-missing state if err := p.runtime.state.UpdatePod(p); err != nil { @@ -65,6 +57,13 @@ func (p *Pod) refresh() error { return ErrPodRemoved } + // Retrieve the pod's lock + lock, err := p.runtime.lockManager.RetrieveLock(p.config.LockID) + if err != nil { + return errors.Wrapf(err, "error retrieving lock for pod %s", p.ID()) + } + p.lock = lock + // We need to recreate the pod's cgroup if p.config.UsePodCgroup { switch p.runtime.config.CgroupManager { diff --git a/libpod/runtime.go b/libpod/runtime.go index f390824dc..c7000d84a 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -1,6 +1,7 @@ package libpod import ( + "fmt" "io/ioutil" "os" "os/exec" @@ -11,6 +12,7 @@ import ( is "github.com/containers/image/storage" "github.com/containers/image/types" "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/libpod/lock" "github.com/containers/libpod/pkg/firewall" sysreg "github.com/containers/libpod/pkg/registries" "github.com/containers/libpod/pkg/rootless" @@ -61,6 +63,14 @@ const ( DefaultInfraImage = "k8s.gcr.io/pause:3.1" // DefaultInfraCommand to be run in an infra container DefaultInfraCommand = "/pause" + + // DefaultInitPath is the default path to the container-init binary + DefaultInitPath = "/usr/libexec/podman/catatonit" + + // DefaultSHMLockPath is the default path for SHM locks + DefaultSHMLockPath = "/libpod_lock" + // DefaultRootlessSHMLockPath is the default path for rootless SHM locks + DefaultRootlessSHMLockPath = "/libpod_rootless_lock" ) // A RuntimeOption is a functional option which alters the Runtime created by @@ -75,17 +85,25 @@ type Runtime struct { storageService *storageService imageContext *types.SystemContext ociRuntime *OCIRuntime - lockDir string netPlugin ocicni.CNIPlugin - ociRuntimePath string + ociRuntimePath OCIRuntimePath conmonPath string valid bool lock sync.RWMutex imageRuntime *image.Runtime firewallBackend firewall.FirewallBackend + lockManager lock.Manager configuredFrom *runtimeConfiguredFrom } +// OCIRuntimePath contains information about an OCI runtime. +type OCIRuntimePath struct { + // Name of the runtime to refer to by the --runtime flag + Name string `toml:"name"` + // Paths to check for this executable + Paths []string `toml:"paths"` +} + // RuntimeConfig contains configuration options used to set up the runtime type RuntimeConfig struct { // StorageConfig is the configuration used by containers/storage @@ -108,10 +126,10 @@ type RuntimeConfig struct { // cause conflicts in containers/storage // As such this is not exposed via the config file StateType RuntimeStateStore `toml:"-"` - // RuntimePath is the path to OCI runtime binary for launching - // containers - // The first path pointing to a valid file will be used - RuntimePath []string `toml:"runtime_path"` + // OCIRuntime is the OCI runtime to use. + OCIRuntime string `toml:"runtime"` + // OCIRuntimes are the set of configured OCI runtimes (default is runc) + OCIRuntimes map[string][]string `toml:"runtimes"` // ConmonPath is the path to the Conmon binary used for managing // containers // The first path pointing to a valid file will be used @@ -122,6 +140,8 @@ type RuntimeConfig struct { // CGroupManager is the CGroup Manager to use // Valid values are "cgroupfs" and "systemd" CgroupManager string `toml:"cgroup_manager"` + // InitPath is the path to the container-init binary. + InitPath string `toml:"init_path"` // StaticDir is the path to a persistent directory to store container // files StaticDir string `toml:"static_dir"` @@ -160,6 +180,7 @@ type RuntimeConfig struct { // and all containers and pods will be visible. // The default namespace is "". Namespace string `toml:"namespace,omitempty"` + // InfraImage is the image a pod infra container will use to manage namespaces InfraImage string `toml:"infra_image"` // InfraCommand is the command run to start up a pod infra container @@ -174,6 +195,10 @@ type RuntimeConfig struct { EnablePortReservation bool `toml:"enable_port_reservation"` // EnableLabeling indicates wether libpod will support container labeling EnableLabeling bool `toml:"label"` + + // NumLocks is the number of locks to make available for containers and + // pods. + NumLocks uint32 `toml:"num_locks,omitempty"` } // runtimeConfiguredFrom is a struct used during early runtime init to help @@ -196,14 +221,17 @@ var ( StorageConfig: storage.StoreOptions{}, ImageDefaultTransport: DefaultTransport, StateType: BoltDBStateStore, - RuntimePath: []string{ - "/usr/bin/runc", - "/usr/sbin/runc", - "/usr/local/bin/runc", - "/usr/local/sbin/runc", - "/sbin/runc", - "/bin/runc", - "/usr/lib/cri-o-runc/sbin/runc", + OCIRuntime: "runc", + OCIRuntimes: map[string][]string{ + "runc": { + "/usr/bin/runc", + "/usr/sbin/runc", + "/usr/local/bin/runc", + "/usr/local/sbin/runc", + "/sbin/runc", + "/bin/runc", + "/usr/lib/cri-o-runc/sbin/runc", + }, }, ConmonPath: []string{ "/usr/libexec/podman/conmon", @@ -217,6 +245,7 @@ var ( ConmonEnvVars: []string{ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", }, + InitPath: DefaultInitPath, CgroupManager: SystemdCgroupsManager, StaticDir: filepath.Join(storage.DefaultStoreOptions.GraphRoot, "libpod"), TmpDir: "", @@ -228,6 +257,7 @@ var ( InfraImage: DefaultInfraImage, EnablePortReservation: true, EnableLabeling: true, + NumLocks: 2048, } ) @@ -395,8 +425,9 @@ func NewRuntimeFromConfig(configPath string, options ...RuntimeOption) (runtime runtime.config = new(RuntimeConfig) runtime.configuredFrom = new(runtimeConfiguredFrom) - // Set two fields not in the TOML config + // Set three fields not in the TOML config runtime.config.StateType = defaultRuntimeConfig.StateType + runtime.config.OCIRuntime = defaultRuntimeConfig.OCIRuntime runtime.config.StorageConfig = storage.StoreOptions{} // Check to see if the given configuration file exists @@ -434,22 +465,35 @@ func NewRuntimeFromConfig(configPath string, options ...RuntimeOption) (runtime func makeRuntime(runtime *Runtime) (err error) { // Find a working OCI runtime binary foundRuntime := false - for _, path := range runtime.config.RuntimePath { - stat, err := os.Stat(path) - if err != nil { - continue - } - if stat.IsDir() { - continue - } + // If runtime is an absolute path, then use it as it is. + if runtime.config.OCIRuntime[0] == '/' { foundRuntime = true - runtime.ociRuntimePath = path - break + runtime.ociRuntimePath = OCIRuntimePath{Name: filepath.Base(runtime.config.OCIRuntime), Paths: []string{runtime.config.OCIRuntime}} + } else { + // If not, look it up in the configuration. + paths := runtime.config.OCIRuntimes[runtime.config.OCIRuntime] + if paths != nil { + for _, path := range paths { + stat, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + continue + } + return errors.Wrapf(err, "cannot stat %s", path) + } + if !stat.Mode().IsRegular() { + continue + } + foundRuntime = true + runtime.ociRuntimePath = OCIRuntimePath{Name: runtime.config.OCIRuntime, Paths: []string{path}} + break + } + } } if !foundRuntime { return errors.Wrapf(ErrInvalidArg, "could not find a working binary (configured options: %v)", - runtime.config.RuntimePath) + runtime.config.OCIRuntimes) } // Find a working conmon binary @@ -605,7 +649,7 @@ func makeRuntime(runtime *Runtime) (err error) { } // Make an OCI runtime to perform container operations - ociRuntime, err := newOCIRuntime("runc", runtime.ociRuntimePath, + ociRuntime, err := newOCIRuntime(runtime.ociRuntimePath, runtime.conmonPath, runtime.config.ConmonEnvVars, runtime.config.CgroupManager, runtime.config.TmpDir, runtime.config.MaxLogSize, runtime.config.NoPivotRoot, @@ -615,17 +659,6 @@ func makeRuntime(runtime *Runtime) (err error) { } runtime.ociRuntime = ociRuntime - // Make a directory to hold container lockfiles - lockDir := filepath.Join(runtime.config.TmpDir, "lock") - if err := os.MkdirAll(lockDir, 0755); err != nil { - // The directory is allowed to exist - if !os.IsExist(err) { - return errors.Wrapf(err, "error creating runtime lockfiles directory %s", - lockDir) - } - } - runtime.lockDir = lockDir - // Make the per-boot files directory if it does not exist if err := os.MkdirAll(runtime.config.TmpDir, 0755); err != nil { // The directory is allowed to exist @@ -670,6 +703,7 @@ func makeRuntime(runtime *Runtime) (err error) { // and use it to lock important operations aliveLock.Lock() locked := true + doRefresh := false defer func() { if locked { aliveLock.Unlock() @@ -682,22 +716,46 @@ func makeRuntime(runtime *Runtime) (err error) { // empty state only creates a single file // As such, it's not really a performance concern if os.IsNotExist(err) { - if os.Geteuid() != 0 { - aliveLock.Unlock() - locked = false - if err2 := runtime.refreshRootless(); err2 != nil { - return err2 - } - } else { - if err2 := runtime.refresh(runtimeAliveFile); err2 != nil { - return err2 - } - } + doRefresh = true } else { return errors.Wrapf(err, "error reading runtime status file %s", runtimeAliveFile) } } + lockPath := DefaultSHMLockPath + if rootless.IsRootless() { + lockPath = fmt.Sprintf("%s_%d", DefaultRootlessSHMLockPath, rootless.GetRootlessUID()) + } + // Set up the lock manager + manager, err := lock.OpenSHMLockManager(lockPath, runtime.config.NumLocks) + if err != nil { + if os.IsNotExist(errors.Cause(err)) { + manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks) + if err != nil { + return err + } + } else { + return err + } + } + runtime.lockManager = manager + + // If we need to refresh the state, do it now - things are guaranteed to + // be set up by now. + if doRefresh { + if os.Geteuid() != 0 { + aliveLock.Unlock() + locked = false + if err2 := runtime.refreshRootless(); err2 != nil { + return err2 + } + } else { + if err2 := runtime.refresh(runtimeAliveFile); err2 != nil { + return err2 + } + } + } + // Mark the runtime as valid - ready to be used, cannot be modified // further runtime.valid = true @@ -771,7 +829,11 @@ func (r *Runtime) refreshRootless() error { // Take advantage of a command that requires a new userns // so that we are running as the root user and able to use refresh() cmd := exec.Command(os.Args[0], "info") - return cmd.Run() + err := cmd.Run() + if err != nil { + return errors.Wrapf(err, "Error running %s info while refreshing state", os.Args[0]) + } + return nil } // Reconfigures the runtime after a reboot @@ -793,19 +855,22 @@ func (r *Runtime) refresh(alivePath string) error { if err != nil { return errors.Wrapf(err, "error retrieving all pods from state") } + // No locks are taken during pod and container refresh. + // Furthermore, the pod and container refresh() functions are not + // allowed to take locks themselves. + // We cannot assume that any pod or container has a valid lock until + // after this function has returned. + // The runtime alive lock should suffice to provide mutual exclusion + // until this has run. for _, ctr := range ctrs { - ctr.lock.Lock() if err := ctr.refresh(); err != nil { logrus.Errorf("Error refreshing container %s: %v", ctr.ID(), err) } - ctr.lock.Unlock() } for _, pod := range pods { - pod.lock.Lock() if err := pod.refresh(); err != nil { logrus.Errorf("Error refreshing pod %s: %v", pod.ID(), err) } - pod.lock.Unlock() } // Create a file indicating the runtime is alive and ready diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index a9095c6d1..6d5ce5a7e 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -9,7 +9,6 @@ import ( "time" "github.com/containers/libpod/pkg/rootless" - "github.com/containers/storage" "github.com/containers/storage/pkg/stringid" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" @@ -48,8 +47,8 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options .. } ctr := new(Container) - ctr.config = new(Config) - ctr.state = new(containerState) + ctr.config = new(ContainerConfig) + ctr.state = new(ContainerState) ctr.config.ID = stringid.GenerateNonCryptoID() @@ -61,17 +60,10 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options .. ctr.state.BindMounts = make(map[string]string) - // Path our lock file will reside at - lockPath := filepath.Join(r.lockDir, ctr.config.ID) - // Grab a lockfile at the given path - lock, err := storage.GetLockfile(lockPath) - if err != nil { - return nil, errors.Wrapf(err, "error creating lockfile for new container") - } - ctr.lock = lock - ctr.config.StopTimeout = CtrRemoveTimeout + ctr.config.OCIRuntime = r.config.OCIRuntime + // Set namespace based on current runtime namespace // Do so before options run so they can override it if r.config.Namespace != "" { @@ -85,6 +77,19 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options .. } } + // Allocate a lock for the container + lock, err := r.lockManager.AllocateLock() + if err != nil { + return nil, errors.Wrapf(err, "error allocating lock for new container") + } + ctr.lock = lock + ctr.config.LockID = ctr.lock.ID() + logrus.Debugf("Allocated lock %d for container %s", ctr.lock.ID(), ctr.ID()) + + ctr.valid = true + ctr.state.State = ContainerStateConfigured + ctr.runtime = r + ctr.valid = true ctr.state.State = ContainerStateConfigured @@ -379,6 +384,15 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool) } } + // Deallocate the container's lock + if err := c.lock.Free(); err != nil { + if cleanupErr == nil { + cleanupErr = err + } else { + logrus.Errorf("free container lock: %v", err) + } + } + return cleanupErr } diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go index 3d6fad52f..c6d497c0c 100644 --- a/libpod/runtime_pod_linux.go +++ b/libpod/runtime_pod_linux.go @@ -23,7 +23,7 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (*Pod, return nil, ErrRuntimeStopped } - pod, err := newPod(r.lockDir, r) + pod, err := newPod(r) if err != nil { return nil, errors.Wrapf(err, "error creating pod") } @@ -48,6 +48,14 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (*Pod, pod.config.Name = name } + // Allocate a lock for the pod + lock, err := r.lockManager.AllocateLock() + if err != nil { + return nil, errors.Wrapf(err, "error allocating lock for new pod") + } + pod.lock = lock + pod.config.LockID = pod.lock.ID() + pod.valid = true // Check CGroup parent sanity, and set it if it was not set @@ -239,6 +247,11 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) return err } } + + // Free the container's lock + if err := ctr.lock.Free(); err != nil { + return err + } } // Remove containers from the state diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go index 5cc0938f0..0727cfedf 100644 --- a/libpod/runtime_volume_linux.go +++ b/libpod/runtime_volume_linux.go @@ -8,7 +8,6 @@ import ( "path/filepath" "strings" - "github.com/containers/storage" "github.com/containers/storage/pkg/stringid" "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" @@ -68,14 +67,12 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption) } volume.config.MountPoint = fullVolPath - // Path our lock file will reside at - lockPath := filepath.Join(r.lockDir, volume.config.Name) - // Grab a lockfile at the given path - lock, err := storage.GetLockfile(lockPath) + lock, err := r.lockManager.AllocateLock() if err != nil { - return nil, errors.Wrapf(err, "error creating lockfile for new volume") + return nil, errors.Wrapf(err, "error allocating lock for new volume") } volume.lock = lock + volume.config.LockID = volume.lock.ID() volume.valid = true diff --git a/libpod/runtime_volume_unsupported.go b/libpod/runtime_volume_unsupported.go new file mode 100644 index 000000000..d87459759 --- /dev/null +++ b/libpod/runtime_volume_unsupported.go @@ -0,0 +1,19 @@ +// +build !linux + +package libpod + +import ( + "context" +) + +func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force, prune bool) error { + return ErrNotImplemented +} + +func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption) (*Volume, error) { + return nil, ErrNotImplemented +} + +func (r *Runtime) NewVolume(ctx context.Context, options ...VolumeCreateOption) (*Volume, error) { + return nil, ErrNotImplemented +} diff --git a/libpod/state_test.go b/libpod/state_test.go index 708ce7d4e..4bd00ab55 100644 --- a/libpod/state_test.go +++ b/libpod/state_test.go @@ -8,16 +8,17 @@ import ( "testing" "time" + "github.com/containers/libpod/libpod/lock" "github.com/containers/storage" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -// Returns state, tmp directory containing all state files, locks directory -// (subdirectory of tmp dir), and error +// Returns state, tmp directory containing all state files, lock manager, and +// error. // Closing the state and removing the given tmp directory should be sufficient -// to clean up -type emptyStateFunc func() (State, string, string, error) +// to clean up. +type emptyStateFunc func() (State, string, lock.Manager, error) const ( tmpDirPrefix = "libpod_state_test_" @@ -31,10 +32,10 @@ var ( ) // Get an empty BoltDB state for use in tests -func getEmptyBoltState() (s State, p string, p2 string, err error) { +func getEmptyBoltState() (s State, p string, m lock.Manager, err error) { tmpDir, err := ioutil.TempDir("", tmpDirPrefix) if err != nil { - return nil, "", "", err + return nil, "", nil, err } defer func() { if err != nil { @@ -43,30 +44,30 @@ func getEmptyBoltState() (s State, p string, p2 string, err error) { }() dbPath := filepath.Join(tmpDir, "db.sql") - lockDir := filepath.Join(tmpDir, "locks") - if err := os.Mkdir(lockDir, 0755); err != nil { - return nil, "", "", err + lockManager, err := lock.NewInMemoryManager(16) + if err != nil { + return nil, "", nil, err } runtime := new(Runtime) runtime.config = new(RuntimeConfig) runtime.config.StorageConfig = storage.StoreOptions{} - runtime.lockDir = lockDir + runtime.lockManager = lockManager state, err := NewBoltState(dbPath, runtime) if err != nil { - return nil, "", "", err + return nil, "", nil, err } - return state, tmpDir, lockDir, nil + return state, tmpDir, lockManager, nil } // Get an empty in-memory state for use in tests -func getEmptyInMemoryState() (s State, p string, p2 string, err error) { +func getEmptyInMemoryState() (s State, p string, m lock.Manager, err error) { tmpDir, err := ioutil.TempDir("", tmpDirPrefix) if err != nil { - return nil, "", "", err + return nil, "", nil, err } defer func() { if err != nil { @@ -76,17 +77,20 @@ func getEmptyInMemoryState() (s State, p string, p2 string, err error) { state, err := NewInMemoryState() if err != nil { - return nil, "", "", err + return nil, "", nil, err + } + + lockManager, err := lock.NewInMemoryManager(16) + if err != nil { + return nil, "", nil, err } - // Don't need a separate locks dir as InMemoryState stores nothing on - // disk - return state, tmpDir, tmpDir, nil + return state, tmpDir, lockManager, nil } -func runForAllStates(t *testing.T, testFunc func(*testing.T, State, string)) { +func runForAllStates(t *testing.T, testFunc func(*testing.T, State, lock.Manager)) { for stateName, stateFunc := range testedStates { - state, path, lockPath, err := stateFunc() + state, path, manager, err := stateFunc() if err != nil { t.Fatalf("Error initializing state %s: %v", stateName, err) } @@ -94,7 +98,7 @@ func runForAllStates(t *testing.T, testFunc func(*testing.T, State, string)) { defer state.Close() success := t.Run(stateName, func(t *testing.T) { - testFunc(t, state, lockPath) + testFunc(t, state, manager) }) if !success { t.Fail() @@ -103,8 +107,8 @@ func runForAllStates(t *testing.T, testFunc func(*testing.T, State, string)) { } func TestAddAndGetContainer(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -118,10 +122,10 @@ func TestAddAndGetContainer(t *testing.T) { } func TestAddAndGetContainerFromMultiple(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) err = state.AddContainer(testCtr1) @@ -138,8 +142,8 @@ func TestAddAndGetContainerFromMultiple(t *testing.T) { } func TestGetContainerPodSameIDFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -151,17 +155,17 @@ func TestGetContainerPodSameIDFails(t *testing.T) { } func TestAddInvalidContainerFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - err := state.AddContainer(&Container{config: &Config{ID: "1234"}}) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + err := state.AddContainer(&Container{config: &ContainerConfig{ID: "1234"}}) assert.Error(t, err) }) } func TestAddDuplicateCtrIDFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestContainer(testCtr1.ID(), "test2", lockPath) + testCtr2, err := getTestContainer(testCtr1.ID(), "test2", manager) assert.NoError(t, err) err = state.AddContainer(testCtr1) @@ -177,10 +181,10 @@ func TestAddDuplicateCtrIDFails(t *testing.T) { } func TestAddDuplicateCtrNameFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestContainer(strings.Repeat("2", 32), testCtr1.Name(), lockPath) + testCtr2, err := getTestContainer(strings.Repeat("2", 32), testCtr1.Name(), manager) assert.NoError(t, err) err = state.AddContainer(testCtr1) @@ -196,10 +200,10 @@ func TestAddDuplicateCtrNameFails(t *testing.T) { } func TestAddCtrPodDupIDFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestContainer(testPod.ID(), "testCtr", lockPath) + testCtr, err := getTestContainer(testPod.ID(), "testCtr", manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -215,10 +219,10 @@ func TestAddCtrPodDupIDFails(t *testing.T) { } func TestAddCtrPodDupNameFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestContainer(strings.Repeat("2", 32), testPod.Name(), lockPath) + testCtr, err := getTestContainer(strings.Repeat("2", 32), testPod.Name(), manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -234,11 +238,11 @@ func TestAddCtrPodDupNameFails(t *testing.T) { } func TestAddCtrInPodFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -256,16 +260,16 @@ func TestAddCtrInPodFails(t *testing.T) { } func TestAddCtrDepInPodFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) testCtr1.config.Pod = testPod.ID() - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr2.config.UserNsCtr = testCtr1.ID() @@ -288,10 +292,10 @@ func TestAddCtrDepInPodFails(t *testing.T) { } func TestAddCtrDepInSameNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) testCtr2.config.UserNsCtr = testCtr1.config.ID @@ -312,10 +316,10 @@ func TestAddCtrDepInSameNamespaceSucceeds(t *testing.T) { } func TestAddCtrDepInDifferentNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) testCtr2.config.UserNsCtr = testCtr1.config.ID @@ -338,8 +342,8 @@ func TestAddCtrDepInDifferentNamespaceFails(t *testing.T) { } func TestAddCtrSameNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -357,8 +361,8 @@ func TestAddCtrSameNamespaceSucceeds(t *testing.T) { } func TestAddCtrDifferentNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -377,22 +381,22 @@ func TestAddCtrDifferentNamespaceFails(t *testing.T) { } func TestGetNonexistentContainerFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.Container("does not exist") assert.Error(t, err) }) } func TestGetContainerWithEmptyIDFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.Container("") assert.Error(t, err) }) } func TestGetContainerInDifferentNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test2" @@ -408,8 +412,8 @@ func TestGetContainerInDifferentNamespaceFails(t *testing.T) { } func TestGetContainerInSameNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -427,8 +431,8 @@ func TestGetContainerInSameNamespaceSucceeds(t *testing.T) { } func TestGetContainerInNamespaceWhileNotInNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -444,22 +448,22 @@ func TestGetContainerInNamespaceWhileNotInNamespaceSucceeds(t *testing.T) { } func TestLookupContainerWithEmptyIDFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.LookupContainer("") assert.Error(t, err) }) } func TestLookupNonexistentContainerFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.LookupContainer("does not exist") assert.Error(t, err) }) } func TestLookupContainerByFullID(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -473,8 +477,8 @@ func TestLookupContainerByFullID(t *testing.T) { } func TestLookupContainerByUniquePartialID(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -488,10 +492,10 @@ func TestLookupContainerByUniquePartialID(t *testing.T) { } func TestLookupContainerByNonUniquePartialIDFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestContainer(strings.Repeat("0", 32), "test1", lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestContainer(strings.Repeat("0", 32), "test1", manager) assert.NoError(t, err) - testCtr2, err := getTestContainer(strings.Repeat("0", 31)+"1", "test2", lockPath) + testCtr2, err := getTestContainer(strings.Repeat("0", 31)+"1", "test2", manager) assert.NoError(t, err) err = state.AddContainer(testCtr1) @@ -506,8 +510,8 @@ func TestLookupContainerByNonUniquePartialIDFails(t *testing.T) { } func TestLookupContainerByName(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -521,8 +525,8 @@ func TestLookupContainerByName(t *testing.T) { } func TestLookupCtrByPodNameFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -534,8 +538,8 @@ func TestLookupCtrByPodNameFails(t *testing.T) { } func TestLookupCtrByPodIDFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -547,8 +551,8 @@ func TestLookupCtrByPodIDFails(t *testing.T) { } func TestLookupCtrInSameNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -566,8 +570,8 @@ func TestLookupCtrInSameNamespaceSucceeds(t *testing.T) { } func TestLookupCtrInDifferentNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -583,11 +587,11 @@ func TestLookupCtrInDifferentNamespaceFails(t *testing.T) { } func TestLookupContainerMatchInDifferentNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestContainer(strings.Repeat("0", 32), "test1", lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestContainer(strings.Repeat("0", 32), "test1", manager) assert.NoError(t, err) testCtr1.config.Namespace = "test2" - testCtr2, err := getTestContainer(strings.Repeat("0", 31)+"1", "test2", lockPath) + testCtr2, err := getTestContainer(strings.Repeat("0", 31)+"1", "test2", manager) assert.NoError(t, err) testCtr2.config.Namespace = "test1" @@ -607,14 +611,14 @@ func TestLookupContainerMatchInDifferentNamespaceSucceeds(t *testing.T) { } func TestHasContainerEmptyIDFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.HasContainer("") assert.Error(t, err) }) } func TestHasContainerNoSuchContainerReturnsFalse(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { exists, err := state.HasContainer("does not exist") assert.NoError(t, err) assert.False(t, exists) @@ -622,8 +626,8 @@ func TestHasContainerNoSuchContainerReturnsFalse(t *testing.T) { } func TestHasContainerFindsContainer(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -636,8 +640,8 @@ func TestHasContainerFindsContainer(t *testing.T) { } func TestHasContainerPodIDIsFalse(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -650,8 +654,8 @@ func TestHasContainerPodIDIsFalse(t *testing.T) { } func TestHasContainerSameNamespaceIsTrue(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -668,8 +672,8 @@ func TestHasContainerSameNamespaceIsTrue(t *testing.T) { } func TestHasContainerDifferentNamespaceIsFalse(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -686,8 +690,8 @@ func TestHasContainerDifferentNamespaceIsFalse(t *testing.T) { } func TestSaveAndUpdateContainer(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -711,8 +715,8 @@ func TestSaveAndUpdateContainer(t *testing.T) { } func TestSaveAndUpdateContainerSameNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -740,8 +744,8 @@ func TestSaveAndUpdateContainerSameNamespaceSucceeds(t *testing.T) { } func TestUpdateContainerNotInDatabaseReturnsError(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.UpdateContainer(testCtr) @@ -751,15 +755,15 @@ func TestUpdateContainerNotInDatabaseReturnsError(t *testing.T) { } func TestUpdateInvalidContainerReturnsError(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - err := state.UpdateContainer(&Container{config: &Config{ID: "1234"}}) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + err := state.UpdateContainer(&Container{config: &ContainerConfig{ID: "1234"}}) assert.Error(t, err) }) } func TestUpdateContainerNotInNamespaceReturnsError(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -775,15 +779,15 @@ func TestUpdateContainerNotInNamespaceReturnsError(t *testing.T) { } func TestSaveInvalidContainerReturnsError(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - err := state.SaveContainer(&Container{config: &Config{ID: "1234"}}) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + err := state.SaveContainer(&Container{config: &ContainerConfig{ID: "1234"}}) assert.Error(t, err) }) } func TestSaveContainerNotInStateReturnsError(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.SaveContainer(testCtr) @@ -793,8 +797,8 @@ func TestSaveContainerNotInStateReturnsError(t *testing.T) { } func TestSaveContainerNotInNamespaceReturnsError(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -810,8 +814,8 @@ func TestSaveContainerNotInNamespaceReturnsError(t *testing.T) { } func TestRemoveContainer(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -831,8 +835,8 @@ func TestRemoveContainer(t *testing.T) { } func TestRemoveNonexistantContainerFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.RemoveContainer(testCtr) @@ -842,8 +846,8 @@ func TestRemoveNonexistantContainerFails(t *testing.T) { } func TestRemoveContainerNotInNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -869,7 +873,7 @@ func TestRemoveContainerNotInNamespaceFails(t *testing.T) { } func TestGetAllContainersOnNewStateIsEmpty(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { ctrs, err := state.AllContainers() assert.NoError(t, err) assert.Equal(t, 0, len(ctrs)) @@ -877,8 +881,8 @@ func TestGetAllContainersOnNewStateIsEmpty(t *testing.T) { } func TestGetAllContainersWithOneContainer(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -893,10 +897,10 @@ func TestGetAllContainersWithOneContainer(t *testing.T) { } func TestGetAllContainersTwoContainers(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) err = state.AddContainer(testCtr1) @@ -912,8 +916,8 @@ func TestGetAllContainersTwoContainers(t *testing.T) { } func TestGetAllContainersNoContainerInNamespace(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -930,13 +934,13 @@ func TestGetAllContainersNoContainerInNamespace(t *testing.T) { } func TestGetContainerOneContainerInNamespace(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) testCtr1.config.Namespace = "test1" - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) err = state.AddContainer(testCtr1) @@ -956,15 +960,15 @@ func TestGetContainerOneContainerInNamespace(t *testing.T) { } func TestContainerInUseInvalidContainer(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.ContainerInUse(&Container{}) assert.Error(t, err) }) } func TestContainerInUseCtrNotInState(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) _, err = state.ContainerInUse(testCtr) assert.Error(t, err) @@ -972,8 +976,8 @@ func TestContainerInUseCtrNotInState(t *testing.T) { } func TestContainerInUseCtrNotInNamespace(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -989,10 +993,10 @@ func TestContainerInUseCtrNotInNamespace(t *testing.T) { } func TestContainerInUseOneContainer(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) testCtr2.config.UserNsCtr = testCtr1.config.ID @@ -1011,12 +1015,12 @@ func TestContainerInUseOneContainer(t *testing.T) { } func TestContainerInUseTwoContainers(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) - testCtr3, err := getTestCtrN("3", lockPath) + testCtr3, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr2.config.UserNsCtr = testCtr1.config.ID @@ -1038,10 +1042,10 @@ func TestContainerInUseTwoContainers(t *testing.T) { } func TestContainerInUseOneContainerMultipleDependencies(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) testCtr2.config.UserNsCtr = testCtr1.config.ID @@ -1061,10 +1065,10 @@ func TestContainerInUseOneContainerMultipleDependencies(t *testing.T) { } func TestContainerInUseGenericDependency(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) testCtr2.config.Dependencies = []string{testCtr1.config.ID} @@ -1083,12 +1087,12 @@ func TestContainerInUseGenericDependency(t *testing.T) { } func TestContainerInUseMultipleGenericDependencies(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) - testCtr3, err := getTestCtrN("3", lockPath) + testCtr3, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr3.config.Dependencies = []string{testCtr1.config.ID, testCtr2.config.ID} @@ -1115,10 +1119,10 @@ func TestContainerInUseMultipleGenericDependencies(t *testing.T) { } func TestContainerInUseGenericAndNamespaceDependencies(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) testCtr2.config.Dependencies = []string{testCtr1.config.ID} @@ -1138,10 +1142,10 @@ func TestContainerInUseGenericAndNamespaceDependencies(t *testing.T) { } func TestCannotRemoveContainerWithDependency(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) testCtr2.config.UserNsCtr = testCtr1.config.ID @@ -1162,10 +1166,10 @@ func TestCannotRemoveContainerWithDependency(t *testing.T) { } func TestCannotRemoveContainerWithGenericDependency(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) testCtr2.config.Dependencies = []string{testCtr1.config.ID} @@ -1186,10 +1190,10 @@ func TestCannotRemoveContainerWithGenericDependency(t *testing.T) { } func TestCanRemoveContainerAfterDependencyRemoved(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) testCtr2.config.UserNsCtr = testCtr1.ID() @@ -1213,10 +1217,10 @@ func TestCanRemoveContainerAfterDependencyRemoved(t *testing.T) { } func TestCanRemoveContainerAfterDependencyRemovedDuplicate(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr1, err := getTestCtr1(manager) assert.NoError(t, err) - testCtr2, err := getTestCtr2(lockPath) + testCtr2, err := getTestCtr2(manager) assert.NoError(t, err) testCtr2.config.UserNsCtr = testCtr1.ID() @@ -1241,11 +1245,11 @@ func TestCanRemoveContainerAfterDependencyRemovedDuplicate(t *testing.T) { } func TestCannotUsePodAsDependency(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) - testPod, err := getTestPod2(lockPath) + testPod, err := getTestPod2(manager) assert.NoError(t, err) testCtr.config.UserNsCtr = testPod.ID() @@ -1263,8 +1267,8 @@ func TestCannotUsePodAsDependency(t *testing.T) { } func TestCannotUseBadIDAsDependency(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.UserNsCtr = strings.Repeat("5", 32) @@ -1279,8 +1283,8 @@ func TestCannotUseBadIDAsDependency(t *testing.T) { } func TestCannotUseBadIDAsGenericDependency(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) testCtr.config.Dependencies = []string{strings.Repeat("5", 32)} @@ -1295,22 +1299,22 @@ func TestCannotUseBadIDAsGenericDependency(t *testing.T) { } func TestGetPodDoesNotExist(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.Pod("doesnotexist") assert.Error(t, err) }) } func TestGetPodEmptyID(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.Pod("") assert.Error(t, err) }) } func TestGetPodOnePod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -1324,11 +1328,11 @@ func TestGetPodOnePod(t *testing.T) { } func TestGetOnePodFromTwo(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod1, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod1, err := getTestPod1(manager) assert.NoError(t, err) - testPod2, err := getTestPod2(lockPath) + testPod2, err := getTestPod2(manager) assert.NoError(t, err) err = state.AddPod(testPod1) @@ -1345,11 +1349,11 @@ func TestGetOnePodFromTwo(t *testing.T) { } func TestGetNotExistPodWithPods(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod1, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod1, err := getTestPod1(manager) assert.NoError(t, err) - testPod2, err := getTestPod2(lockPath) + testPod2, err := getTestPod2(manager) assert.NoError(t, err) err = state.AddPod(testPod1) @@ -1364,8 +1368,8 @@ func TestGetNotExistPodWithPods(t *testing.T) { } func TestGetPodByCtrID(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -1377,8 +1381,8 @@ func TestGetPodByCtrID(t *testing.T) { } func TestGetPodInNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -1396,8 +1400,8 @@ func TestGetPodInNamespaceSucceeds(t *testing.T) { } func TestGetPodPodNotInNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -1413,22 +1417,22 @@ func TestGetPodPodNotInNamespaceFails(t *testing.T) { } func TestLookupPodEmptyID(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.LookupPod("") assert.Error(t, err) }) } func TestLookupNotExistPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.LookupPod("doesnotexist") assert.Error(t, err) }) } func TestLookupPodFullID(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -1442,8 +1446,8 @@ func TestLookupPodFullID(t *testing.T) { } func TestLookupPodUniquePartialID(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -1457,11 +1461,11 @@ func TestLookupPodUniquePartialID(t *testing.T) { } func TestLookupPodNonUniquePartialID(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod1, err := getTestPod(strings.Repeat("1", 32), "test1", lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod1, err := getTestPod(strings.Repeat("1", 32), "test1", manager) assert.NoError(t, err) - testPod2, err := getTestPod(strings.Repeat("1", 31)+"2", "test2", lockPath) + testPod2, err := getTestPod(strings.Repeat("1", 31)+"2", "test2", manager) assert.NoError(t, err) err = state.AddPod(testPod1) @@ -1476,8 +1480,8 @@ func TestLookupPodNonUniquePartialID(t *testing.T) { } func TestLookupPodByName(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -1491,8 +1495,8 @@ func TestLookupPodByName(t *testing.T) { } func TestLookupPodByCtrID(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -1504,8 +1508,8 @@ func TestLookupPodByCtrID(t *testing.T) { } func TestLookupPodByCtrName(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -1517,8 +1521,8 @@ func TestLookupPodByCtrName(t *testing.T) { } func TestLookupPodInSameNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -1536,8 +1540,8 @@ func TestLookupPodInSameNamespaceSucceeds(t *testing.T) { } func TestLookupPodInDifferentNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -1553,13 +1557,13 @@ func TestLookupPodInDifferentNamespaceFails(t *testing.T) { } func TestLookupPodOneInDifferentNamespaceFindsRightPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod1, err := getTestPod(strings.Repeat("1", 32), "test1", lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod1, err := getTestPod(strings.Repeat("1", 32), "test1", manager) assert.NoError(t, err) testPod1.config.Namespace = "test1" - testPod2, err := getTestPod(strings.Repeat("1", 31)+"2", "test2", lockPath) + testPod2, err := getTestPod(strings.Repeat("1", 31)+"2", "test2", manager) assert.NoError(t, err) testPod2.config.Namespace = "test2" @@ -1580,14 +1584,14 @@ func TestLookupPodOneInDifferentNamespaceFindsRightPod(t *testing.T) { } func TestHasPodEmptyIDErrors(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.HasPod("") assert.Error(t, err) }) } func TestHasPodNoSuchPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { exist, err := state.HasPod("notexist") assert.NoError(t, err) assert.False(t, exist) @@ -1595,8 +1599,8 @@ func TestHasPodNoSuchPod(t *testing.T) { } func TestHasPodWrongIDFalse(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -1609,8 +1613,8 @@ func TestHasPodWrongIDFalse(t *testing.T) { } func TestHasPodRightIDTrue(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -1623,8 +1627,8 @@ func TestHasPodRightIDTrue(t *testing.T) { } func TestHasPodCtrIDFalse(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -1637,8 +1641,8 @@ func TestHasPodCtrIDFalse(t *testing.T) { } func TestHasPodSameNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -1655,8 +1659,8 @@ func TestHasPodSameNamespaceSucceeds(t *testing.T) { } func TestHasPodDifferentNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -1673,15 +1677,15 @@ func TestHasPodDifferentNamespaceFails(t *testing.T) { } func TestAddPodInvalidPodErrors(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { err := state.AddPod(&Pod{config: &PodConfig{}}) assert.Error(t, err) }) } func TestAddPodValidPodSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -1696,11 +1700,11 @@ func TestAddPodValidPodSucceeds(t *testing.T) { } func TestAddPodDuplicateIDFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod1, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod1, err := getTestPod1(manager) assert.NoError(t, err) - testPod2, err := getTestPod(testPod1.ID(), "testpod2", lockPath) + testPod2, err := getTestPod(testPod1.ID(), "testpod2", manager) assert.NoError(t, err) err = state.AddPod(testPod1) @@ -1716,11 +1720,11 @@ func TestAddPodDuplicateIDFails(t *testing.T) { } func TestAddPodDuplicateNameFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod1, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod1, err := getTestPod1(manager) assert.NoError(t, err) - testPod2, err := getTestPod(strings.Repeat("2", 32), testPod1.Name(), lockPath) + testPod2, err := getTestPod(strings.Repeat("2", 32), testPod1.Name(), manager) assert.NoError(t, err) err = state.AddPod(testPod1) @@ -1736,11 +1740,11 @@ func TestAddPodDuplicateNameFails(t *testing.T) { } func TestAddPodNonDuplicateSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod1, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod1, err := getTestPod1(manager) assert.NoError(t, err) - testPod2, err := getTestPod2(lockPath) + testPod2, err := getTestPod2(manager) assert.NoError(t, err) err = state.AddPod(testPod1) @@ -1756,11 +1760,11 @@ func TestAddPodNonDuplicateSucceeds(t *testing.T) { } func TestAddPodCtrIDConflictFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) - testPod, err := getTestPod(testCtr.ID(), "testpod1", lockPath) + testPod, err := getTestPod(testCtr.ID(), "testpod1", manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -1776,11 +1780,11 @@ func TestAddPodCtrIDConflictFails(t *testing.T) { } func TestAddPodCtrNameConflictFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) - testPod, err := getTestPod(strings.Repeat("3", 32), testCtr.Name(), lockPath) + testPod, err := getTestPod(strings.Repeat("3", 32), testCtr.Name(), manager) assert.NoError(t, err) err = state.AddContainer(testCtr) @@ -1796,8 +1800,8 @@ func TestAddPodCtrNameConflictFails(t *testing.T) { } func TestAddPodSameNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -1816,8 +1820,8 @@ func TestAddPodSameNamespaceSucceeds(t *testing.T) { } func TestAddPodDifferentNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -1836,15 +1840,15 @@ func TestAddPodDifferentNamespaceFails(t *testing.T) { } func TestRemovePodInvalidPodErrors(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { err := state.RemovePod(&Pod{config: &PodConfig{}}) assert.Error(t, err) }) } func TestRemovePodNotInStateFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.RemovePod(testPod) @@ -1854,8 +1858,8 @@ func TestRemovePodNotInStateFails(t *testing.T) { } func TestRemovePodSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -1871,11 +1875,11 @@ func TestRemovePodSucceeds(t *testing.T) { } func TestRemovePodFromPods(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod1, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod1, err := getTestPod1(manager) assert.NoError(t, err) - testPod2, err := getTestPod2(lockPath) + testPod2, err := getTestPod2(manager) assert.NoError(t, err) err = state.AddPod(testPod1) @@ -1896,11 +1900,11 @@ func TestRemovePodFromPods(t *testing.T) { } func TestRemovePodNotEmptyFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -1920,11 +1924,11 @@ func TestRemovePodNotEmptyFails(t *testing.T) { } func TestRemovePodAfterEmptySucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -1947,8 +1951,8 @@ func TestRemovePodAfterEmptySucceeds(t *testing.T) { } func TestRemovePodNotInNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -1970,7 +1974,7 @@ func TestRemovePodNotInNamespaceFails(t *testing.T) { } func TestAllPodsEmptyOnEmptyState(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { allPods, err := state.AllPods() assert.NoError(t, err) assert.Equal(t, 0, len(allPods)) @@ -1978,8 +1982,8 @@ func TestAllPodsEmptyOnEmptyState(t *testing.T) { } func TestAllPodsFindsPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -1994,14 +1998,14 @@ func TestAllPodsFindsPod(t *testing.T) { } func TestAllPodsMultiplePods(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod1, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod1, err := getTestPod1(manager) assert.NoError(t, err) - testPod2, err := getTestPod2(lockPath) + testPod2, err := getTestPod2(manager) assert.NoError(t, err) - testPod3, err := getTestPodN("3", lockPath) + testPod3, err := getTestPodN("3", manager) assert.NoError(t, err) allPods1, err := state.AllPods() @@ -2032,8 +2036,8 @@ func TestAllPodsMultiplePods(t *testing.T) { } func TestAllPodsPodInDifferentNamespaces(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -2050,13 +2054,13 @@ func TestAllPodsPodInDifferentNamespaces(t *testing.T) { } func TestAllPodsOnePodInDifferentNamespace(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod1, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod1, err := getTestPod1(manager) assert.NoError(t, err) testPod1.config.Namespace = "test1" - testPod2, err := getTestPod2(lockPath) + testPod2, err := getTestPod2(manager) assert.NoError(t, err) testPod2.config.Namespace = "test2" @@ -2078,15 +2082,15 @@ func TestAllPodsOnePodInDifferentNamespace(t *testing.T) { } func TestPodHasContainerNoSuchPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.PodHasContainer(&Pod{config: &PodConfig{}}, strings.Repeat("0", 32)) assert.Error(t, err) }) } func TestPodHasContainerEmptyCtrID(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -2098,8 +2102,8 @@ func TestPodHasContainerEmptyCtrID(t *testing.T) { } func TestPodHasContainerNoSuchCtr(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -2112,11 +2116,11 @@ func TestPodHasContainerNoSuchCtr(t *testing.T) { } func TestPodHasContainerCtrNotInPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -2132,11 +2136,11 @@ func TestPodHasContainerCtrNotInPod(t *testing.T) { } func TestPodHasContainerSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -2154,8 +2158,8 @@ func TestPodHasContainerSucceeds(t *testing.T) { } func TestPodHasContainerPodNotInNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -2171,15 +2175,15 @@ func TestPodHasContainerPodNotInNamespaceFails(t *testing.T) { } func TestPodContainersByIDInvalidPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.PodContainersByID(&Pod{config: &PodConfig{}}) assert.Error(t, err) }) } func TestPodContainerdByIDPodNotInState(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) _, err = state.PodContainersByID(testPod) @@ -2189,8 +2193,8 @@ func TestPodContainerdByIDPodNotInState(t *testing.T) { } func TestPodContainersByIDEmptyPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -2203,11 +2207,11 @@ func TestPodContainersByIDEmptyPod(t *testing.T) { } func TestPodContainersByIDOneContainer(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -2226,19 +2230,19 @@ func TestPodContainersByIDOneContainer(t *testing.T) { } func TestPodContainersByIDMultipleContainers(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) testCtr1.config.Pod = testPod.ID() - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr2.config.Pod = testPod.ID() - testCtr3, err := getTestCtrN("4", lockPath) + testCtr3, err := getTestCtrN("4", manager) assert.NoError(t, err) testCtr3.config.Pod = testPod.ID() @@ -2273,8 +2277,8 @@ func TestPodContainersByIDMultipleContainers(t *testing.T) { } func TestPodContainerByIDPodNotInNamespace(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -2290,15 +2294,15 @@ func TestPodContainerByIDPodNotInNamespace(t *testing.T) { } func TestPodContainersInvalidPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { _, err := state.PodContainers(&Pod{config: &PodConfig{}}) assert.Error(t, err) }) } func TestPodContainersPodNotInState(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) _, err = state.PodContainers(testPod) @@ -2308,8 +2312,8 @@ func TestPodContainersPodNotInState(t *testing.T) { } func TestPodContainersEmptyPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -2322,11 +2326,11 @@ func TestPodContainersEmptyPod(t *testing.T) { } func TestPodContainersOneContainer(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -2346,19 +2350,19 @@ func TestPodContainersOneContainer(t *testing.T) { } func TestPodContainersMultipleContainers(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) testCtr1.config.Pod = testPod.ID() - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr2.config.Pod = testPod.ID() - testCtr3, err := getTestCtrN("4", lockPath) + testCtr3, err := getTestCtrN("4", manager) assert.NoError(t, err) testCtr3.config.Pod = testPod.ID() @@ -2393,8 +2397,8 @@ func TestPodContainersMultipleContainers(t *testing.T) { } func TestPodContainersPodNotInNamespace(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -2410,15 +2414,15 @@ func TestPodContainersPodNotInNamespace(t *testing.T) { } func TestRemovePodContainersInvalidPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { err := state.RemovePodContainers(&Pod{config: &PodConfig{}}) assert.Error(t, err) }) } func TestRemovePodContainersPodNotInState(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.RemovePodContainers(testPod) @@ -2428,8 +2432,8 @@ func TestRemovePodContainersPodNotInState(t *testing.T) { } func TestRemovePodContainersNoContainers(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -2445,11 +2449,11 @@ func TestRemovePodContainersNoContainers(t *testing.T) { } func TestRemovePodContainersOneContainer(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -2469,15 +2473,15 @@ func TestRemovePodContainersOneContainer(t *testing.T) { } func TestRemovePodContainersPreservesCtrOutsidePod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) testCtr1.config.Pod = testPod.ID() - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -2503,15 +2507,15 @@ func TestRemovePodContainersPreservesCtrOutsidePod(t *testing.T) { } func TestRemovePodContainersTwoContainers(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) testCtr1.config.Pod = testPod.ID() - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr2.config.Pod = testPod.ID() @@ -2534,15 +2538,15 @@ func TestRemovePodContainersTwoContainers(t *testing.T) { } func TestRemovePodContainerDependencyInPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) testCtr1.config.Pod = testPod.ID() - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr2.config.Pod = testPod.ID() testCtr2.config.IPCNsCtr = testCtr1.ID() @@ -2566,8 +2570,8 @@ func TestRemovePodContainerDependencyInPod(t *testing.T) { } func TestRemoveContainersNotInNamespace(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -2583,8 +2587,8 @@ func TestRemoveContainersNotInNamespace(t *testing.T) { } func TestAddContainerToPodInvalidPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.AddContainerToPod(&Pod{config: &PodConfig{}}, testCtr) @@ -2593,14 +2597,14 @@ func TestAddContainerToPodInvalidPod(t *testing.T) { } func TestAddContainerToPodInvalidCtr(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) assert.NoError(t, err) - err = state.AddContainerToPod(testPod, &Container{config: &Config{ID: "1234"}}) + err = state.AddContainerToPod(testPod, &Container{config: &ContainerConfig{ID: "1234"}}) assert.Error(t, err) ctrs, err := state.PodContainersByID(testPod) @@ -2610,11 +2614,11 @@ func TestAddContainerToPodInvalidCtr(t *testing.T) { } func TestAddContainerToPodPodNotInState(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -2625,11 +2629,11 @@ func TestAddContainerToPodPodNotInState(t *testing.T) { } func TestAddContainerToPodSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -2653,15 +2657,15 @@ func TestAddContainerToPodSucceeds(t *testing.T) { } func TestAddContainerToPodTwoContainers(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) testCtr1.config.Pod = testPod.ID() - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr2.config.Pod = testPod.ID() @@ -2685,15 +2689,15 @@ func TestAddContainerToPodTwoContainers(t *testing.T) { } func TestAddContainerToPodWithAddContainer(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) testCtr1.config.Pod = testPod.ID() - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -2718,14 +2722,14 @@ func TestAddContainerToPodWithAddContainer(t *testing.T) { } func TestAddContainerToPodCtrIDConflict(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) - testCtr2, err := getTestContainer(testCtr1.ID(), "testCtr3", lockPath) + testCtr2, err := getTestContainer(testCtr1.ID(), "testCtr3", manager) assert.NoError(t, err) testCtr2.config.Pod = testPod.ID() @@ -2749,14 +2753,14 @@ func TestAddContainerToPodCtrIDConflict(t *testing.T) { } func TestAddContainerToPodCtrNameConflict(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) - testCtr2, err := getTestContainer(strings.Repeat("4", 32), testCtr1.Name(), lockPath) + testCtr2, err := getTestContainer(strings.Repeat("4", 32), testCtr1.Name(), manager) assert.NoError(t, err) testCtr2.config.Pod = testPod.ID() @@ -2780,11 +2784,11 @@ func TestAddContainerToPodCtrNameConflict(t *testing.T) { } func TestAddContainerToPodPodIDConflict(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestContainer(testPod.ID(), "testCtr", lockPath) + testCtr, err := getTestContainer(testPod.ID(), "testCtr", manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -2805,11 +2809,11 @@ func TestAddContainerToPodPodIDConflict(t *testing.T) { } func TestAddContainerToPodPodNameConflict(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestContainer(strings.Repeat("2", 32), testPod.Name(), lockPath) + testCtr, err := getTestContainer(strings.Repeat("2", 32), testPod.Name(), manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -2830,15 +2834,15 @@ func TestAddContainerToPodPodNameConflict(t *testing.T) { } func TestAddContainerToPodAddsDependencies(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) testCtr1.config.Pod = testPod.ID() - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr2.config.Pod = testPod.ID() testCtr2.config.IPCNsCtr = testCtr1.ID() @@ -2860,11 +2864,11 @@ func TestAddContainerToPodAddsDependencies(t *testing.T) { } func TestAddContainerToPodPodDependencyFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() testCtr.config.IPCNsCtr = testPod.ID() @@ -2882,11 +2886,11 @@ func TestAddContainerToPodPodDependencyFails(t *testing.T) { } func TestAddContainerToPodBadDependencyFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() testCtr.config.IPCNsCtr = strings.Repeat("8", 32) @@ -2904,14 +2908,14 @@ func TestAddContainerToPodBadDependencyFails(t *testing.T) { } func TestAddContainerToPodDependencyOutsidePodFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr2.config.Pod = testPod.ID() testCtr2.config.IPCNsCtr = testCtr1.ID() @@ -2940,17 +2944,17 @@ func TestAddContainerToPodDependencyOutsidePodFails(t *testing.T) { } func TestAddContainerToPodDependencyInSameNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) testCtr1.config.Pod = testPod.ID() testCtr1.config.Namespace = "test1" - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr2.config.Pod = testPod.ID() testCtr2.config.IPCNsCtr = testCtr1.ID() @@ -2973,17 +2977,17 @@ func TestAddContainerToPodDependencyInSameNamespaceSucceeds(t *testing.T) { } func TestAddContainerToPodDependencyInSeparateNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) testCtr1.config.Pod = testPod.ID() testCtr1.config.Namespace = "test1" - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr2.config.Pod = testPod.ID() testCtr2.config.IPCNsCtr = testCtr1.ID() @@ -3013,12 +3017,12 @@ func TestAddContainerToPodDependencyInSeparateNamespaceFails(t *testing.T) { } func TestAddContainerToPodSameNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" testCtr.config.Pod = testPod.ID() @@ -3037,12 +3041,12 @@ func TestAddContainerToPodSameNamespaceSucceeds(t *testing.T) { } func TestAddContainerToPodDifferentNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Namespace = "test2" testCtr.config.Pod = testPod.ID() @@ -3060,11 +3064,11 @@ func TestAddContainerToPodDifferentNamespaceFails(t *testing.T) { } func TestAddContainerToPodNamespaceOnCtrFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" testCtr.config.Pod = testPod.ID() @@ -3082,12 +3086,12 @@ func TestAddContainerToPodNamespaceOnCtrFails(t *testing.T) { } func TestAddContainerToPodNamespaceOnPodFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -3104,11 +3108,11 @@ func TestAddContainerToPodNamespaceOnPodFails(t *testing.T) { } func TestAddCtrToPodSameNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) - testPod, err := getTestPod2(lockPath) + testPod, err := getTestPod2(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -3131,11 +3135,11 @@ func TestAddCtrToPodSameNamespaceSucceeds(t *testing.T) { } func TestAddCtrToPodDifferentNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) - testPod, err := getTestPod2(lockPath) + testPod, err := getTestPod2(manager) assert.NoError(t, err) testCtr.config.Namespace = "test1" @@ -3159,8 +3163,8 @@ func TestAddCtrToPodDifferentNamespaceFails(t *testing.T) { } func TestRemoveContainerFromPodBadPodFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testCtr, err := getTestCtr1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testCtr, err := getTestCtr1(manager) assert.NoError(t, err) err = state.RemoveContainerFromPod(&Pod{config: &PodConfig{}}, testCtr) @@ -3169,11 +3173,11 @@ func TestRemoveContainerFromPodBadPodFails(t *testing.T) { } func TestRemoveContainerFromPodPodNotInStateFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -3185,11 +3189,11 @@ func TestRemoveContainerFromPodPodNotInStateFails(t *testing.T) { } func TestRemoveContainerFromPodCtrNotInStateFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -3204,11 +3208,11 @@ func TestRemoveContainerFromPodCtrNotInStateFails(t *testing.T) { } func TestRemoveContainerFromPodCtrNotInPodFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -3229,11 +3233,11 @@ func TestRemoveContainerFromPodCtrNotInPodFails(t *testing.T) { } func TestRemoveContainerFromPodSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -3257,15 +3261,15 @@ func TestRemoveContainerFromPodSucceeds(t *testing.T) { } func TestRemoveContainerFromPodWithDependencyFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) testCtr1.config.Pod = testPod.ID() - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr2.config.Pod = testPod.ID() testCtr2.config.IPCNsCtr = testCtr1.ID() @@ -3293,15 +3297,15 @@ func TestRemoveContainerFromPodWithDependencyFails(t *testing.T) { } func TestRemoveContainerFromPodWithDependencySucceedsAfterDepRemoved(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) - testCtr1, err := getTestCtr2(lockPath) + testCtr1, err := getTestCtr2(manager) assert.NoError(t, err) testCtr1.config.Pod = testPod.ID() - testCtr2, err := getTestCtrN("3", lockPath) + testCtr2, err := getTestCtrN("3", manager) assert.NoError(t, err) testCtr2.config.Pod = testPod.ID() testCtr2.config.IPCNsCtr = testCtr1.ID() @@ -3332,13 +3336,13 @@ func TestRemoveContainerFromPodWithDependencySucceedsAfterDepRemoved(t *testing. } func TestRemoveContainerFromPodSameNamespaceSucceeds(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -3366,13 +3370,13 @@ func TestRemoveContainerFromPodSameNamespaceSucceeds(t *testing.T) { } func TestRemoveContainerFromPodDifferentNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" - testCtr, err := getTestCtr2(lockPath) + testCtr, err := getTestCtr2(manager) assert.NoError(t, err) testCtr.config.Pod = testPod.ID() @@ -3402,15 +3406,15 @@ func TestRemoveContainerFromPodDifferentNamespaceFails(t *testing.T) { } func TestUpdatePodInvalidPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { err := state.UpdatePod(&Pod{config: &PodConfig{}}) assert.Error(t, err) }) } func TestUpdatePodPodNotInStateFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.UpdatePod(testPod) @@ -3419,8 +3423,8 @@ func TestUpdatePodPodNotInStateFails(t *testing.T) { } func TestUpdatePodNotInNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -3436,15 +3440,15 @@ func TestUpdatePodNotInNamespaceFails(t *testing.T) { } func TestSavePodInvalidPod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { err := state.SavePod(&Pod{config: &PodConfig{}}) assert.Error(t, err) }) } func TestSavePodPodNotInStateFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.SavePod(testPod) @@ -3453,8 +3457,8 @@ func TestSavePodPodNotInStateFails(t *testing.T) { } func TestSavePodNotInNamespaceFails(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" @@ -3470,8 +3474,8 @@ func TestSavePodNotInNamespaceFails(t *testing.T) { } func TestSaveAndUpdatePod(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) err = state.AddPod(testPod) @@ -3495,8 +3499,8 @@ func TestSaveAndUpdatePod(t *testing.T) { } func TestSaveAndUpdatePodSameNamespace(t *testing.T) { - runForAllStates(t, func(t *testing.T, state State, lockPath string) { - testPod, err := getTestPod1(lockPath) + runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) { + testPod, err := getTestPod1(manager) assert.NoError(t, err) testPod.config.Namespace = "test1" diff --git a/libpod/storage.go b/libpod/storage.go index 10026efda..17d231171 100644 --- a/libpod/storage.go +++ b/libpod/storage.go @@ -2,7 +2,6 @@ package libpod import ( "context" - "encoding/json" "time" istorage "github.com/containers/image/storage" diff --git a/libpod/version.go b/libpod/version.go index 966588ae9..d2b99a275 100644 --- a/libpod/version.go +++ b/libpod/version.go @@ -19,11 +19,12 @@ var ( //Version is an output struct for varlink type Version struct { - Version string - GoVersion string - GitCommit string - Built int64 - OsArch string + RemoteAPIVersion int64 + Version string + GoVersion string + GitCommit string + Built int64 + OsArch string } // GetVersion returns a VersionOutput struct for varlink and podman @@ -39,10 +40,11 @@ func GetVersion() (Version, error) { } } return Version{ - Version: podmanVersion.Version, - GoVersion: runtime.Version(), - GitCommit: gitCommit, - Built: buildTime, - OsArch: runtime.GOOS + "/" + runtime.GOARCH, + RemoteAPIVersion: podmanVersion.RemoteAPIVersion, + Version: podmanVersion.Version, + GoVersion: runtime.Version(), + GitCommit: gitCommit, + Built: buildTime, + OsArch: runtime.GOOS + "/" + runtime.GOARCH, }, nil } diff --git a/libpod/volume.go b/libpod/volume.go index b732e8aa7..026a3bf49 100644 --- a/libpod/volume.go +++ b/libpod/volume.go @@ -1,6 +1,6 @@ package libpod -import "github.com/containers/storage" +import "github.com/containers/libpod/libpod/lock" // Volume is the type used to create named volumes // TODO: all volumes should be created using this and the Volume API @@ -9,13 +9,17 @@ type Volume struct { valid bool runtime *Runtime - lock storage.Locker + lock lock.Locker } // VolumeConfig holds the volume's config information //easyjson:json type VolumeConfig struct { - Name string `json:"name"` + // Name of the volume + Name string `json:"name"` + // ID of this volume's lock + LockID uint32 `json:"lockID"` + Labels map[string]string `json:"labels"` MountPoint string `json:"mountPoint"` Driver string `json:"driver"` |