diff options
36 files changed, 115 insertions, 2143 deletions
diff --git a/contrib/cirrus/logformatter b/contrib/cirrus/logformatter index 3fa0e5618..5156f9f8a 100755 --- a/contrib/cirrus/logformatter +++ b/contrib/cirrus/logformatter @@ -243,11 +243,17 @@ END_HTML $cirrus_task = $1; } - # BATS handling (used also for apiv2 tests, which emit TAP output) - if ($line =~ /^1\.\.(\d+)$/ || $line =~ m!/test-apiv2!) { + # BATS handling. This will recognize num_tests both at start and end + if ($line =~ /^1\.\.(\d+)$/) { $looks_like_bats = 1; $bats_count{expected_total} = $1; } + # Since the number of tests can't always be predicted, recognize + # some leading text strings that indicate BATS output to come. + elsif ($line =~ /^TAP\s+version\s/ || $line =~ m!/test-apiv2!) { + $looks_like_bats = 1; + $bats_count{expected_total} = -1; # Expect to be overridden at end! + } if ($looks_like_bats) { my $css; @@ -11,10 +11,10 @@ require ( github.com/containernetworking/cni v0.8.1 github.com/containernetworking/plugins v0.9.1 github.com/containers/buildah v1.20.1-0.20210402144408-36a37402d0c8 - github.com/containers/common v0.35.4 + github.com/containers/common v0.36.0 github.com/containers/conmon v2.0.20+incompatible github.com/containers/image/v5 v5.11.0 - github.com/containers/ocicrypt v1.1.0 + github.com/containers/ocicrypt v1.1.1 github.com/containers/psgo v1.5.2 github.com/containers/storage v1.29.0 github.com/coreos/go-systemd/v22 v22.3.1 @@ -61,7 +61,7 @@ require ( github.com/vbauerster/mpb/v6 v6.0.3 github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 go.etcd.io/bbolt v1.3.5 - golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad + golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a golang.org/x/sys v0.0.0-20210324051608-47abb6519492 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 @@ -192,8 +192,9 @@ github.com/containernetworking/plugins v0.9.1 h1:FD1tADPls2EEi3flPc2OegIY1M9pUa9 github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= github.com/containers/buildah v1.20.1-0.20210402144408-36a37402d0c8 h1:RlqbDlfE3+qrq4bNTZG7NVPqCDzfZrgE/yicu0VAykQ= github.com/containers/buildah v1.20.1-0.20210402144408-36a37402d0c8/go.mod h1:iowyscoAC5jwNDhs3c5CLGdBZ9FJk5UOoN2I5TdmXFs= -github.com/containers/common v0.35.4 h1:szyWRncsHkBwCVpu1dkEOXUjkwCetlfcLmKJTwo1Sp8= github.com/containers/common v0.35.4/go.mod h1:rMzxgD7nMGw++cEbsp+NZv0UJO4rgXbm7F7IbJPTwIE= +github.com/containers/common v0.36.0 h1:7/0GM3oi2ROmKAg/8pDWJ8BU2BXdbmy7Gk2/SFCTV38= +github.com/containers/common v0.36.0/go.mod h1:rMzxgD7nMGw++cEbsp+NZv0UJO4rgXbm7F7IbJPTwIE= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/image/v5 v5.10.5/go.mod h1:SgIbWEedCNBbn2FI5cH0/jed1Ecy2s8XK5zTxvJTzII= @@ -203,8 +204,9 @@ github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDpl github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY= github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= github.com/containers/ocicrypt v1.0.3/go.mod h1:CUBa+8MRNL/VkpxYIpaMtgn1WgXGyvPQj8jcy0EVG6g= -github.com/containers/ocicrypt v1.1.0 h1:A6UzSUFMla92uxO43O6lm86i7evMGjTY7wTKB2DyGPY= github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= +github.com/containers/ocicrypt v1.1.1 h1:prL8l9w3ntVqXvNH1CiNn5ENjcCnr38JqpSyvKKB4GI= +github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= github.com/containers/psgo v1.5.2 h1:3aoozst/GIwsrr/5jnFy3FrJay98uujPCu9lTuSZ/Cw= github.com/containers/psgo v1.5.2/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU= github.com/containers/storage v1.23.5/go.mod h1:ha26Q6ngehFNhf3AWoXldvAvwI4jFe3ETQAf/CeZPyM= @@ -852,8 +854,9 @@ golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -926,8 +929,9 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 h1:OgUuv8lsRpBibGNbSizVwKWlysjaNzmC9gYMhPVfqFM= golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go deleted file mode 100644 index df45f8e73..000000000 --- a/libpod/in_memory_state.go +++ /dev/null @@ -1,1706 +0,0 @@ -package libpod - -import ( - "strings" - - "github.com/containers/podman/v3/libpod/define" - "github.com/containers/podman/v3/pkg/registrar" - "github.com/containers/storage/pkg/truncindex" - "github.com/pkg/errors" -) - -// TODO: Maybe separate idIndex for pod/containers -// As of right now, partial IDs used in Lookup... need to be unique as well -// This may be undesirable? - -// An InMemoryState is a purely in-memory state store -type InMemoryState struct { - // Maps pod ID to pod struct. - pods map[string]*Pod - // Maps container ID to container struct. - containers map[string]*Container - // Maps volume ID to volume struct - volumes map[string]*Volume - // Maps exec session ID to ID of associated container - execSessions map[string]string - // Maps container ID to a list of IDs of dependencies. - ctrDepends map[string][]string - // Maps volume ID to IDs of dependencies - volumeDepends map[string][]string - // Maps container ID to IDs of associated exec sessions. - ctrExecSessions map[string][]string - // Maps pod ID to a map of container ID to container struct. - podContainers map[string]map[string]*Container - ctrNetworks map[string][]string - // Maps container ID to network name to list of aliases. - ctrNetworkAliases map[string]map[string][]string - // Global name registry - ensures name uniqueness and performs lookups. - nameIndex *registrar.Registrar - // Global ID registry - ensures ID uniqueness and performs lookups. - idIndex *truncindex.TruncIndex - // Namespace the state is joined to. - namespace string - // Maps namespace name to local ID and name registries for looking up - // pods and containers in a specific namespace. - namespaceIndexes map[string]*namespaceIndex -} - -// namespaceIndex contains name and ID registries for a specific namespace. -// This is used for namespaces lookup operations. -type namespaceIndex struct { - nameIndex *registrar.Registrar - idIndex *truncindex.TruncIndex -} - -// NewInMemoryState initializes a new, empty in-memory state -func NewInMemoryState() (State, error) { - state := new(InMemoryState) - - state.pods = make(map[string]*Pod) - state.containers = make(map[string]*Container) - state.volumes = make(map[string]*Volume) - state.execSessions = make(map[string]string) - - state.ctrDepends = make(map[string][]string) - state.volumeDepends = make(map[string][]string) - - state.ctrExecSessions = make(map[string][]string) - - state.podContainers = make(map[string]map[string]*Container) - - state.ctrNetworks = make(map[string][]string) - state.ctrNetworkAliases = make(map[string]map[string][]string) - - state.nameIndex = registrar.NewRegistrar() - state.idIndex = truncindex.NewTruncIndex([]string{}) - - state.namespace = "" - - state.namespaceIndexes = make(map[string]*namespaceIndex) - - return state, nil -} - -// Close the state before shutdown -// This is a no-op as we have no backing disk -func (s *InMemoryState) Close() error { - return nil -} - -// Refresh clears container and pod stats after a reboot -// In-memory state won't survive a reboot so this is a no-op -func (s *InMemoryState) Refresh() error { - return nil -} - -// GetDBConfig is not implemented for in-memory state. -// As we do not store a config, return an empty one. -func (s *InMemoryState) GetDBConfig() (*DBConfig, error) { - return &DBConfig{}, nil -} - -// ValidateDBConfig is not implemented for the in-memory state. -// Since we do nothing just return no error. -func (s *InMemoryState) ValidateDBConfig(runtime *Runtime) error { - return nil -} - -// SetNamespace sets the namespace for container and pod retrieval. -func (s *InMemoryState) SetNamespace(ns string) error { - s.namespace = ns - - return nil -} - -// GetName retrieves the name associated with a given ID. -// Works with both Container and Pod IDs. -func (s *InMemoryState) GetName(id string) (string, error) { - if id == "" { - return "", define.ErrEmptyID - } - - var idIndex *truncindex.TruncIndex - if s.namespace != "" { - nsIndex, ok := s.namespaceIndexes[s.namespace] - if !ok { - // We have no containers in the namespace - // Return false - return "", define.ErrNoSuchCtr - } - idIndex = nsIndex.idIndex - } else { - idIndex = s.idIndex - } - - fullID, err := idIndex.Get(id) - if err != nil { - if err == truncindex.ErrNotExist { - return "", define.ErrNoSuchCtr - } - return "", errors.Wrapf(err, "error performing truncindex lookup for ID %s", id) - } - return fullID, nil -} - -// Container retrieves a container from its full ID -func (s *InMemoryState) Container(id string) (*Container, error) { - if id == "" { - return nil, define.ErrEmptyID - } - - ctr, ok := s.containers[id] - if !ok { - return nil, errors.Wrapf(define.ErrNoSuchCtr, "no container with ID %s found", id) - } - - if err := s.checkNSMatch(ctr.ID(), ctr.Namespace()); err != nil { - return nil, err - } - - return ctr, nil -} - -// lookupID retrieves a container or pod ID by full ID, unique partial ID, or -// name -func (s *InMemoryState) lookupID(idOrName string) (string, error) { - var ( - nameIndex *registrar.Registrar - idIndex *truncindex.TruncIndex - ) - - if idOrName == "" { - return "", define.ErrEmptyID - } - - if s.namespace != "" { - nsIndex, ok := s.namespaceIndexes[s.namespace] - if !ok { - // We have no containers in the namespace - // Return false - return "", define.ErrNoSuchCtr - } - nameIndex = nsIndex.nameIndex - idIndex = nsIndex.idIndex - } else { - nameIndex = s.nameIndex - idIndex = s.idIndex - } - - fullID, err := nameIndex.Get(idOrName) - if err != nil { - if err == registrar.ErrNameNotReserved { - // What was passed is not a name, assume it's an ID - fullID, err = idIndex.Get(idOrName) - if err != nil { - if err == truncindex.ErrNotExist { - return "", define.ErrNoSuchCtr - } - return "", errors.Wrapf(err, "error performing truncindex lookup for ID %s", idOrName) - } - } else { - return "", errors.Wrapf(err, "error performing registry lookup for ID %s", idOrName) - } - } - - return fullID, nil -} - -// LookupContainerID retrieves a container ID by full ID, unique partial ID, or -// name -func (s *InMemoryState) LookupContainerID(idOrName string) (string, error) { - fullID, err := s.lookupID(idOrName) - - switch err { - case nil: - _, ok := s.containers[fullID] - if !ok { - // It's a pod, not a container - return "", errors.Wrapf(define.ErrNoSuchCtr, "name or ID %s is a pod, not a container", idOrName) - } - - case define.ErrNoSuchCtr: - return "", errors.Wrapf(define.ErrNoSuchCtr, "no container found with name or ID %s", idOrName) - - default: - return "", err - } - - return fullID, nil -} - -// LookupContainer retrieves a container by full ID, unique partial ID, or name -func (s *InMemoryState) LookupContainer(idOrName string) (*Container, error) { - fullID, err := s.lookupID(idOrName) - - switch err { - case nil: - - case define.ErrNoSuchCtr: - return nil, errors.Wrapf(define.ErrNoSuchCtr, "no container found with name or ID %s", idOrName) - - default: - return nil, err - } - - ctr, ok := s.containers[fullID] - if !ok { - // It's a pod, not a container - return nil, errors.Wrapf(define.ErrNoSuchCtr, "name or ID %s is a pod, not a container", idOrName) - } - - return ctr, nil -} - -// HasContainer checks if a container with the given ID is present in the state -func (s *InMemoryState) HasContainer(id string) (bool, error) { - if id == "" { - return false, define.ErrEmptyID - } - - ctr, ok := s.containers[id] - if !ok || (s.namespace != "" && s.namespace != ctr.config.Namespace) { - return false, nil - } - - return true, nil -} - -// AddContainer adds a container to the state -// Containers in a pod cannot be added to the state -func (s *InMemoryState) AddContainer(ctr *Container) error { - if !ctr.valid { - return errors.Wrapf(define.ErrCtrRemoved, "container with ID %s is not valid", ctr.ID()) - } - - if _, ok := s.containers[ctr.ID()]; ok { - return errors.Wrapf(define.ErrCtrExists, "container with ID %s already exists in state", ctr.ID()) - } - - if ctr.config.Pod != "" { - return errors.Wrapf(define.ErrInvalidArg, "cannot add a container that is in a pod with AddContainer, use AddContainerToPod") - } - - if err := s.checkNSMatch(ctr.ID(), ctr.Namespace()); err != nil { - return err - } - - // Check networks - for _, net := range ctr.config.Networks { - if net == "" { - return errors.Wrapf(define.ErrInvalidArg, "network names cannot be empty") - } - } - - // Check network aliases - for network := range ctr.config.NetworkAliases { - inNet := false - for _, net := range ctr.config.Networks { - if net == network { - inNet = true - break - } - } - if !inNet { - return errors.Wrapf(define.ErrInvalidArg, "container %s has network aliases for network %q but is not joined to network", ctr.ID(), network) - } - } - - // There are potential race conditions with this - // But in-memory state is intended purely for testing and not production - // use, so this should be fine. - depCtrs := ctr.Dependencies() - for _, depID := range depCtrs { - depCtr, ok := s.containers[depID] - if !ok { - return errors.Wrapf(define.ErrNoSuchCtr, "cannot depend on nonexistent container %s", depID) - } else if depCtr.config.Pod != "" { - return errors.Wrapf(define.ErrInvalidArg, "cannot depend on container in a pod if not part of same pod") - } - if depCtr.config.Namespace != ctr.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %s and cannot depend on container %s in namespace %s", ctr.ID(), ctr.config.Namespace, depID, depCtr.config.Namespace) - } - } - - if err := s.nameIndex.Reserve(ctr.Name(), ctr.ID()); err != nil { - return errors.Wrapf(err, "error registering container name %s", ctr.Name()) - } - - if err := s.idIndex.Add(ctr.ID()); err != nil { - s.nameIndex.Release(ctr.Name()) - return errors.Wrapf(err, "error registering container ID %s", ctr.ID()) - } - - s.containers[ctr.ID()] = ctr - - // If we're in a namespace, add us to that namespace's indexes - if ctr.config.Namespace != "" { - var nsIndex *namespaceIndex - nsIndex, ok := s.namespaceIndexes[ctr.config.Namespace] - if !ok { - nsIndex = new(namespaceIndex) - nsIndex.nameIndex = registrar.NewRegistrar() - nsIndex.idIndex = truncindex.NewTruncIndex([]string{}) - s.namespaceIndexes[ctr.config.Namespace] = nsIndex - } - // Should be no errors here, the previous index adds should have caught that - if err := nsIndex.nameIndex.Reserve(ctr.Name(), ctr.ID()); err != nil { - return errors.Wrapf(err, "error registering container name %s", ctr.Name()) - } - if err := nsIndex.idIndex.Add(ctr.ID()); err != nil { - return errors.Wrapf(err, "error registering container ID %s", ctr.ID()) - } - } - - // Add containers this container depends on - for _, depCtr := range depCtrs { - s.addCtrToDependsMap(ctr.ID(), depCtr) - } - - // Add container to volume dependencies - for _, vol := range ctr.config.NamedVolumes { - s.addCtrToVolDependsMap(ctr.ID(), vol.Name) - } - - // Add networks - newNets := make([]string, 0, len(ctr.config.Networks)) - for _, net := range ctr.config.Networks { - if net == "" { - return define.ErrInvalidArg - } - newNets = append(newNets, net) - } - s.ctrNetworks[ctr.ID()] = newNets - - // Add network aliases - s.ctrNetworkAliases[ctr.ID()] = ctr.config.NetworkAliases - - return nil -} - -// RemoveContainer removes a container from the state -// The container will only be removed from the state, not from the pod the container belongs to -func (s *InMemoryState) RemoveContainer(ctr *Container) error { - // Almost no validity checks are performed, to ensure we can kick - // misbehaving containers out of the state - - if err := s.checkNSMatch(ctr.ID(), ctr.Namespace()); err != nil { - return err - } - - // Ensure we don't remove a container which other containers depend on - deps, ok := s.ctrDepends[ctr.ID()] - if ok && len(deps) != 0 { - depsStr := strings.Join(deps, ", ") - return errors.Wrapf(define.ErrDepExists, "the following containers depend on container %s: %s", ctr.ID(), depsStr) - } - - // Ensure we don't have active exec sessions - ctrSessions := s.ctrExecSessions[ctr.ID()] - if len(ctrSessions) > 0 { - sessStr := strings.Join(ctrSessions, ", ") - return errors.Wrapf(define.ErrCtrExists, "the following exec sessions are running for container %s: %s", ctr.ID(), sessStr) - } - - if _, ok := s.containers[ctr.ID()]; !ok { - ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "no container exists in state with ID %s", ctr.ID()) - } - - if err := s.idIndex.Delete(ctr.ID()); err != nil { - return errors.Wrapf(err, "error removing container ID from index") - } - delete(s.containers, ctr.ID()) - s.nameIndex.Release(ctr.Name()) - - delete(s.ctrDepends, ctr.ID()) - - if ctr.config.Namespace != "" { - nsIndex, ok := s.namespaceIndexes[ctr.config.Namespace] - if !ok { - return errors.Wrapf(define.ErrInternal, "error retrieving index for namespace %q", ctr.config.Namespace) - } - if err := nsIndex.idIndex.Delete(ctr.ID()); err != nil { - return errors.Wrapf(err, "error removing container %s from namespace ID index", ctr.ID()) - } - nsIndex.nameIndex.Release(ctr.Name()) - } - - // Remove us from container dependencies - depCtrs := ctr.Dependencies() - for _, depCtr := range depCtrs { - s.removeCtrFromDependsMap(ctr.ID(), depCtr) - } - - // Remove this container from volume dependencies - for _, vol := range ctr.config.NamedVolumes { - s.removeCtrFromVolDependsMap(ctr.ID(), vol.Name) - } - - // Remove our network aliases - delete(s.ctrNetworkAliases, ctr.ID()) - delete(s.ctrNetworks, ctr.ID()) - - return nil -} - -// UpdateContainer updates a container's state -// As all state is in-memory, no update will be required -// As such this is a no-op -func (s *InMemoryState) UpdateContainer(ctr *Container) error { - // If the container is invalid, return error - if !ctr.valid { - return errors.Wrapf(define.ErrCtrRemoved, "container with ID %s is not valid", ctr.ID()) - } - - // If the container does not exist, return error - if _, ok := s.containers[ctr.ID()]; !ok { - ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "container with ID %s not found in state", ctr.ID()) - } - - return s.checkNSMatch(ctr.ID(), ctr.Namespace()) -} - -// SaveContainer saves a container's state -// As all state is in-memory, any changes are always reflected as soon as they -// are made -// As such this is a no-op -func (s *InMemoryState) SaveContainer(ctr *Container) error { - // If the container is invalid, return error - if !ctr.valid { - return errors.Wrapf(define.ErrCtrRemoved, "container with ID %s is not valid", ctr.ID()) - } - - // If the container does not exist, return error - if _, ok := s.containers[ctr.ID()]; !ok { - ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "container with ID %s not found in state", ctr.ID()) - } - - return s.checkNSMatch(ctr.ID(), ctr.Namespace()) -} - -// ContainerInUse checks if the given container is being used by other containers -func (s *InMemoryState) ContainerInUse(ctr *Container) ([]string, error) { - if !ctr.valid { - return nil, define.ErrCtrRemoved - } - - // If the container does not exist, return error - if _, ok := s.containers[ctr.ID()]; !ok { - ctr.valid = false - return nil, errors.Wrapf(define.ErrNoSuchCtr, "container with ID %s not found in state", ctr.ID()) - } - - if err := s.checkNSMatch(ctr.ID(), ctr.Namespace()); err != nil { - return nil, err - } - - arr, ok := s.ctrDepends[ctr.ID()] - if !ok { - return []string{}, nil - } - - return arr, nil -} - -// AllContainers retrieves all containers from the state -func (s *InMemoryState) AllContainers() ([]*Container, error) { - ctrs := make([]*Container, 0, len(s.containers)) - for _, ctr := range s.containers { - if s.namespace == "" || ctr.config.Namespace == s.namespace { - ctrs = append(ctrs, ctr) - } - } - - return ctrs, nil -} - -// Get all networks this container is present in. -func (s *InMemoryState) GetNetworks(ctr *Container) ([]string, error) { - if !ctr.valid { - return nil, define.ErrCtrRemoved - } - - ctr, ok := s.containers[ctr.ID()] - if !ok { - ctr.valid = false - return nil, define.ErrNoSuchCtr - } - - ctrNetworks, ok := s.ctrNetworks[ctr.ID()] - if !ok { - return nil, define.ErrNoSuchNetwork - } - - return ctrNetworks, nil -} - -// GetNetworkAliases returns network aliases for the given container in the -// given network. -func (s *InMemoryState) GetNetworkAliases(ctr *Container, network string) ([]string, error) { - if !ctr.valid { - return nil, define.ErrCtrRemoved - } - - if network == "" { - return nil, errors.Wrapf(define.ErrInvalidArg, "network names must not be empty") - } - - ctr, ok := s.containers[ctr.ID()] - if !ok { - ctr.valid = false - return nil, define.ErrNoSuchCtr - } - - inNet := false - for _, net := range ctr.config.Networks { - if net == network { - inNet = true - } - } - if !inNet { - return nil, define.ErrInvalidArg - } - - ctrAliases, ok := s.ctrNetworkAliases[ctr.ID()] - if !ok { - return []string{}, nil - } - netAliases, ok := ctrAliases[network] - if !ok { - return []string{}, nil - } - - return netAliases, nil -} - -// GetAllNetworkAliases gets all network aliases for the given container. -func (s *InMemoryState) GetAllNetworkAliases(ctr *Container) (map[string][]string, error) { - if !ctr.valid { - return nil, define.ErrCtrRemoved - } - - ctr, ok := s.containers[ctr.ID()] - if !ok { - ctr.valid = false - return nil, define.ErrNoSuchCtr - } - - ctrAliases, ok := s.ctrNetworkAliases[ctr.ID()] - if !ok { - return map[string][]string{}, nil - } - - return ctrAliases, nil -} - -// NetworkConnect connects to the given network -func (s *InMemoryState) NetworkConnect(ctr *Container, network string, aliases []string) error { - if !ctr.valid { - return define.ErrCtrRemoved - } - - if network == "" { - return errors.Wrapf(define.ErrInvalidArg, "network names must not be empty") - } - - ctr, ok := s.containers[ctr.ID()] - if !ok { - ctr.valid = false - return define.ErrNoSuchCtr - } - - inNet := false - ctrNetworks, ok := s.ctrNetworks[ctr.ID()] - if !ok { - return define.ErrNoSuchNetwork - } - for _, net := range ctrNetworks { - if net == network { - inNet = true - } - } - if inNet { - return define.ErrNoSuchNetwork - } - s.ctrNetworks[ctr.ID()] = append(ctrNetworks, network) - - ctrAliases, ok := s.ctrNetworkAliases[ctr.ID()] - if !ok { - ctrAliases = make(map[string][]string) - s.ctrNetworkAliases[ctr.ID()] = ctrAliases - } - ctrAliases[network] = aliases - - return nil -} - -// Disconnect from the given network and remove all aliases in it. -func (s *InMemoryState) NetworkDisconnect(ctr *Container, network string) error { - if !ctr.valid { - return define.ErrCtrRemoved - } - - if network == "" { - return errors.Wrapf(define.ErrInvalidArg, "network names must not be empty") - } - - ctr, ok := s.containers[ctr.ID()] - if !ok { - ctr.valid = false - return define.ErrNoSuchCtr - } - - ctrNetworks, ok := s.ctrNetworks[ctr.ID()] - if !ok { - return define.ErrNoSuchNetwork - } - inNet := false - remainingNets := make([]string, 0, len(ctrNetworks)) - for _, net := range ctrNetworks { - if net == network { - inNet = true - break - } else { - remainingNets = append(remainingNets, net) - } - } - if !inNet { - return define.ErrNoSuchNetwork - } - s.ctrNetworks[ctr.ID()] = remainingNets - - ctrAliases, ok := s.ctrNetworkAliases[ctr.ID()] - if !ok { - ctrAliases = make(map[string][]string) - s.ctrNetworkAliases[ctr.ID()] = ctrAliases - } - delete(ctrAliases, network) - - return nil -} - -// GetContainerConfig returns a container config from the database by full ID -func (s *InMemoryState) GetContainerConfig(id string) (*ContainerConfig, error) { - ctr, err := s.LookupContainer(id) - if err != nil { - return nil, err - } - - return ctr.Config(), nil -} - -// Add an exec session to the database -func (s *InMemoryState) AddExecSession(ctr *Container, session *ExecSession) error { - if !ctr.valid { - return define.ErrCtrRemoved - } - if session.ContainerID() != ctr.ID() { - return errors.Wrapf(define.ErrInvalidArg, "container ID and exec session ID must match") - } - if _, ok := s.containers[ctr.ID()]; !ok { - return define.ErrNoSuchCtr - } - - if _, ok := s.execSessions[session.ID()]; ok { - return define.ErrExecSessionExists - } - - s.execSessions[session.ID()] = ctr.ID() - - ctrSessions, ok := s.ctrExecSessions[ctr.ID()] - if !ok { - ctrSessions = []string{} - } - - ctrSessions = append(ctrSessions, session.ID()) - s.ctrExecSessions[ctr.ID()] = ctrSessions - - return nil -} - -// Get an exec session from the database by full or partial ID. -func (s *InMemoryState) GetExecSession(id string) (string, error) { - if id == "" { - return "", define.ErrEmptyID - } - - session, ok := s.execSessions[id] - if !ok { - return "", define.ErrNoSuchExecSession - } - - return session, nil -} - -// RemoveExecSession removes an exec session from the database. -func (s *InMemoryState) RemoveExecSession(session *ExecSession) error { - if _, ok := s.execSessions[session.ID()]; !ok { - return define.ErrNoSuchExecSession - } - - ctrSessions, ok := s.ctrExecSessions[session.ContainerID()] - // If !ok - internal state seems inconsistent, but the thing we wanted - // to remove is gone. Continue. - if ok { - newSessions := []string{} - for _, sess := range ctrSessions { - if sess != session.ID() { - newSessions = append(newSessions, sess) - } - } - s.ctrExecSessions[session.ContainerID()] = newSessions - } - - delete(s.execSessions, session.ID()) - - return nil -} - -// GetContainerExecSessions retrieves all exec sessions for the given container. -func (s *InMemoryState) GetContainerExecSessions(ctr *Container) ([]string, error) { - if !ctr.valid { - return nil, define.ErrCtrRemoved - } - if _, ok := s.containers[ctr.ID()]; !ok { - ctr.valid = false - return nil, define.ErrNoSuchCtr - } - - ctrSessions := s.ctrExecSessions[ctr.ID()] - - return ctrSessions, nil -} - -// RemoveContainerExecSessions removes all exec sessions for the given -// container. -func (s *InMemoryState) RemoveContainerExecSessions(ctr *Container) error { - if !ctr.valid { - return define.ErrCtrRemoved - } - if _, ok := s.containers[ctr.ID()]; !ok { - ctr.valid = false - return define.ErrNoSuchCtr - } - - ctrSessions, ok := s.ctrExecSessions[ctr.ID()] - if !ok { - return nil - } - - for _, sess := range ctrSessions { - if _, ok := s.execSessions[sess]; !ok { - // We have an internal state inconsistency - // Error out - return errors.Wrapf(define.ErrInternal, "inconsistent database state: exec session %s is missing", sess) - } - delete(s.execSessions, sess) - } - delete(s.ctrExecSessions, ctr.ID()) - - return nil -} - -// RewriteContainerConfig rewrites a container's configuration. -// This function is DANGEROUS, even with an in-memory state. -// Please read the full comment on it in state.go before using it. -func (s *InMemoryState) RewriteContainerConfig(ctr *Container, newCfg *ContainerConfig) error { - if !ctr.valid { - return define.ErrCtrRemoved - } - - // If the container does not exist, return error - stateCtr, ok := s.containers[ctr.ID()] - if !ok { - ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "container with ID %s not found in state", ctr.ID()) - } - - stateCtr.config = newCfg - - return nil -} - -// SafeRewriteContainerConfig rewrites a container's configuration. -// It's safer than RewriteContainerConfig, but still has limitations. Please -// read the comment in state.go before using. -func (s *InMemoryState) SafeRewriteContainerConfig(ctr *Container, oldName, newName string, newCfg *ContainerConfig) error { - if !ctr.valid { - return define.ErrCtrRemoved - } - - if _, err := s.nameIndex.Get(newName); err == nil { - return errors.Wrapf(define.ErrCtrExists, "name %s is in use", newName) - } - - // If the container does not exist, return error - stateCtr, ok := s.containers[ctr.ID()] - if !ok { - ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "container with ID %s not found in state", ctr.ID()) - } - - // Change name in registry. - if s.namespace != "" { - nsIndex, ok := s.namespaceIndexes[s.namespace] - if !ok { - return define.ErrInternal - } - nsIndex.nameIndex.Release(oldName) - if err := nsIndex.nameIndex.Reserve(newName, ctr.ID()); err != nil { - return errors.Wrapf(err, "error registering name %s", newName) - } - } - s.nameIndex.Release(oldName) - if err := s.nameIndex.Reserve(newName, ctr.ID()); err != nil { - return errors.Wrapf(err, "error registering name %s", newName) - } - - stateCtr.config = newCfg - - return nil -} - -// RewritePodConfig rewrites a pod's configuration. -// This function is DANGEROUS, even with in-memory state. -// Please read the full comment on it in state.go before using it. -func (s *InMemoryState) RewritePodConfig(pod *Pod, newCfg *PodConfig) error { - if !pod.valid { - return define.ErrPodRemoved - } - - // If the pod does not exist, return error - statePod, ok := s.pods[pod.ID()] - if !ok { - pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "pod with ID %s not found in state", pod.ID()) - } - - statePod.config = newCfg - - return nil -} - -// RewriteVolumeConfig rewrites a volume's configuration. -// This function is DANGEROUS, even with in-memory state. -// Please read the full comment in state.go before using it. -func (s *InMemoryState) RewriteVolumeConfig(volume *Volume, newCfg *VolumeConfig) error { - if !volume.valid { - return define.ErrVolumeRemoved - } - - // If the volume does not exist, return error - stateVol, ok := s.volumes[volume.Name()] - if !ok { - volume.valid = false - return errors.Wrapf(define.ErrNoSuchVolume, "volume with name %q not found in state", volume.Name()) - } - - stateVol.config = newCfg - - return nil -} - -// Volume retrieves a volume from its full name -func (s *InMemoryState) Volume(name string) (*Volume, error) { - if name == "" { - return nil, define.ErrEmptyID - } - - vol, ok := s.volumes[name] - if !ok { - return nil, errors.Wrapf(define.ErrNoSuchCtr, "no volume with name %s found", name) - } - - return vol, nil -} - -// LookupVolume finds a volume from an unambiguous partial ID. -func (s *InMemoryState) LookupVolume(name string) (*Volume, error) { - if name == "" { - return nil, define.ErrEmptyID - } - - vol, ok := s.volumes[name] - if ok { - return vol, nil - } - - // Alright, we've failed to find by full name. Now comes the expensive - // part. - // Loop through all volumes and look for matches. - var ( - foundMatch bool - candidate *Volume - ) - for volName, vol := range s.volumes { - if strings.HasPrefix(volName, name) { - if foundMatch { - return nil, errors.Wrapf(define.ErrVolumeExists, "more than one result for volume name %q", name) - } - candidate = vol - foundMatch = true - } - } - - if !foundMatch { - return nil, errors.Wrapf(define.ErrNoSuchVolume, "no volume with name %q found", name) - } - - return candidate, nil -} - -// HasVolume checks if a volume with the given name is present in the state -func (s *InMemoryState) HasVolume(name string) (bool, error) { - if name == "" { - return false, define.ErrEmptyID - } - - _, ok := s.volumes[name] - if !ok { - return false, nil - } - - return true, nil -} - -// AddVolume adds a volume to the state -func (s *InMemoryState) AddVolume(volume *Volume) error { - if !volume.valid { - return errors.Wrapf(define.ErrVolumeRemoved, "volume with name %s is not valid", volume.Name()) - } - - if _, ok := s.volumes[volume.Name()]; ok { - return errors.Wrapf(define.ErrVolumeExists, "volume with name %s already exists in state", volume.Name()) - } - - s.volumes[volume.Name()] = volume - - return nil -} - -// RemoveVolume removes a volume from the state -func (s *InMemoryState) RemoveVolume(volume *Volume) error { - // Ensure we don't remove a volume which containers depend on - deps, ok := s.volumeDepends[volume.Name()] - if ok && len(deps) != 0 { - depsStr := strings.Join(deps, ", ") - return errors.Wrapf(define.ErrVolumeExists, "the following containers depend on volume %s: %s", volume.Name(), depsStr) - } - - if _, ok := s.volumes[volume.Name()]; !ok { - volume.valid = false - return errors.Wrapf(define.ErrVolumeRemoved, "no volume exists in state with name %s", volume.Name()) - } - - delete(s.volumes, volume.Name()) - - return nil -} - -// UpdateVolume updates a volume from the database. -// For the in-memory state, this is a no-op. -func (s *InMemoryState) UpdateVolume(volume *Volume) error { - if !volume.valid { - return define.ErrVolumeRemoved - } - - if _, ok := s.volumes[volume.Name()]; !ok { - volume.valid = false - return errors.Wrapf(define.ErrNoSuchVolume, "volume with name %q not found in state", volume.Name()) - } - - return nil -} - -// SaveVolume saves a volume's state to the database. -// For the in-memory state, this is a no-op. -func (s *InMemoryState) SaveVolume(volume *Volume) error { - if !volume.valid { - return define.ErrVolumeRemoved - } - - if _, ok := s.volumes[volume.Name()]; !ok { - volume.valid = false - return errors.Wrapf(define.ErrNoSuchVolume, "volume with name %q not found in state", volume.Name()) - } - - return nil -} - -// VolumeInUse checks if the given volume is being used by at least one container -func (s *InMemoryState) VolumeInUse(volume *Volume) ([]string, error) { - if !volume.valid { - return nil, define.ErrVolumeRemoved - } - - // If the volume does not exist, return error - if _, ok := s.volumes[volume.Name()]; !ok { - volume.valid = false - return nil, errors.Wrapf(define.ErrNoSuchVolume, "volume with name %s not found in state", volume.Name()) - } - - arr, ok := s.volumeDepends[volume.Name()] - if !ok { - return []string{}, nil - } - - return arr, nil -} - -// AllVolumes returns all volumes that exist in the state -func (s *InMemoryState) AllVolumes() ([]*Volume, error) { - allVols := make([]*Volume, 0, len(s.volumes)) - for _, v := range s.volumes { - allVols = append(allVols, v) - } - - return allVols, nil -} - -// Pod retrieves a pod from the state from its full ID -func (s *InMemoryState) Pod(id string) (*Pod, error) { - if id == "" { - return nil, define.ErrEmptyID - } - - pod, ok := s.pods[id] - if !ok { - return nil, errors.Wrapf(define.ErrNoSuchPod, "no pod with id %s found", id) - } - - if err := s.checkNSMatch(pod.ID(), pod.Namespace()); err != nil { - return nil, err - } - - return pod, nil -} - -// LookupPod retrieves a pod from the state from a full or unique partial ID or -// a full name -func (s *InMemoryState) LookupPod(idOrName string) (*Pod, error) { - fullID, err := s.lookupID(idOrName) - - switch err { - case nil: - - case define.ErrNoSuchCtr, define.ErrNoSuchPod: - return nil, errors.Wrapf(define.ErrNoSuchPod, "no pod found with name or ID %s", idOrName) - - default: - return nil, err - } - - pod, ok := s.pods[fullID] - if !ok { - // It's a container not a pod - return nil, errors.Wrapf(define.ErrNoSuchPod, "id or name %s is a container, not a pod", idOrName) - } - - return pod, nil -} - -// HasPod checks if a pod with the given ID is present in the state -func (s *InMemoryState) HasPod(id string) (bool, error) { - if id == "" { - return false, define.ErrEmptyID - } - - pod, ok := s.pods[id] - if !ok || (s.namespace != "" && s.namespace != pod.config.Namespace) { - return false, nil - } - - return true, nil -} - -// PodHasContainer checks if the given pod has a container with the given ID -func (s *InMemoryState) PodHasContainer(pod *Pod, ctrID string) (bool, error) { - if !pod.valid { - return false, errors.Wrapf(define.ErrPodRemoved, "pod %s is not valid", pod.ID()) - } - - if ctrID == "" { - return false, define.ErrEmptyID - } - - if err := s.checkNSMatch(pod.ID(), pod.Namespace()); err != nil { - return false, err - } - - podCtrs, ok := s.podContainers[pod.ID()] - if !ok { - pod.valid = false - return false, errors.Wrapf(define.ErrNoSuchPod, "no pod with ID %s found in state", pod.ID()) - } - - _, ok = podCtrs[ctrID] - return ok, nil -} - -// PodContainersByID returns the IDs of all containers in the given pod -func (s *InMemoryState) PodContainersByID(pod *Pod) ([]string, error) { - if !pod.valid { - return nil, errors.Wrapf(define.ErrPodRemoved, "pod %s is not valid", pod.ID()) - } - - if err := s.checkNSMatch(pod.ID(), pod.Namespace()); err != nil { - return nil, err - } - - podCtrs, ok := s.podContainers[pod.ID()] - if !ok { - pod.valid = false - return nil, errors.Wrapf(define.ErrNoSuchPod, "no pod with ID %s found in state", pod.ID()) - } - - length := len(podCtrs) - if length == 0 { - return []string{}, nil - } - - ctrs := make([]string, 0, length) - for _, ctr := range podCtrs { - ctrs = append(ctrs, ctr.ID()) - } - - return ctrs, nil -} - -// PodContainers retrieves the containers from a pod -func (s *InMemoryState) PodContainers(pod *Pod) ([]*Container, error) { - if !pod.valid { - return nil, errors.Wrapf(define.ErrPodRemoved, "pod %s is not valid", pod.ID()) - } - - if err := s.checkNSMatch(pod.ID(), pod.Namespace()); err != nil { - return nil, err - } - - podCtrs, ok := s.podContainers[pod.ID()] - if !ok { - pod.valid = false - return nil, errors.Wrapf(define.ErrNoSuchPod, "no pod with ID %s found in state", pod.ID()) - } - - length := len(podCtrs) - if length == 0 { - return []*Container{}, nil - } - - ctrs := make([]*Container, 0, length) - for _, ctr := range podCtrs { - ctrs = append(ctrs, ctr) - } - - return ctrs, nil -} - -// AddPod adds a given pod to the state -func (s *InMemoryState) AddPod(pod *Pod) error { - if !pod.valid { - return errors.Wrapf(define.ErrPodRemoved, "pod %s is not valid and cannot be added", pod.ID()) - } - - if err := s.checkNSMatch(pod.ID(), pod.Namespace()); err != nil { - return err - } - - if _, ok := s.pods[pod.ID()]; ok { - return errors.Wrapf(define.ErrPodExists, "pod with ID %s already exists in state", pod.ID()) - } - - if _, ok := s.podContainers[pod.ID()]; ok { - return errors.Wrapf(define.ErrPodExists, "pod with ID %s already exists in state", pod.ID()) - } - - if err := s.nameIndex.Reserve(pod.Name(), pod.ID()); err != nil { - return errors.Wrapf(err, "error registering pod name %s", pod.Name()) - } - - if err := s.idIndex.Add(pod.ID()); err != nil { - s.nameIndex.Release(pod.Name()) - return errors.Wrapf(err, "error registering pod ID %s", pod.ID()) - } - - s.pods[pod.ID()] = pod - - s.podContainers[pod.ID()] = make(map[string]*Container) - - // If we're in a namespace, add us to that namespace's indexes - if pod.config.Namespace != "" { - var nsIndex *namespaceIndex - nsIndex, ok := s.namespaceIndexes[pod.config.Namespace] - if !ok { - nsIndex = new(namespaceIndex) - nsIndex.nameIndex = registrar.NewRegistrar() - nsIndex.idIndex = truncindex.NewTruncIndex([]string{}) - s.namespaceIndexes[pod.config.Namespace] = nsIndex - } - // Should be no errors here, the previous index adds should have caught that - if err := nsIndex.nameIndex.Reserve(pod.Name(), pod.ID()); err != nil { - return errors.Wrapf(err, "error registering container name %s", pod.Name()) - } - if err := nsIndex.idIndex.Add(pod.ID()); err != nil { - return errors.Wrapf(err, "error registering container ID %s", pod.ID()) - } - } - - return nil -} - -// RemovePod removes a given pod from the state -// Only empty pods can be removed -func (s *InMemoryState) RemovePod(pod *Pod) error { - // Don't make many validity checks to ensure we can kick badly formed - // pods out of the state - - if err := s.checkNSMatch(pod.ID(), pod.Namespace()); err != nil { - return err - } - - if _, ok := s.pods[pod.ID()]; !ok { - pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "no pod exists in state with ID %s", pod.ID()) - } - podCtrs, ok := s.podContainers[pod.ID()] - if !ok { - pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "no pod exists in state with ID %s", pod.ID()) - } - if len(podCtrs) != 0 { - return errors.Wrapf(define.ErrCtrExists, "pod %s is not empty and cannot be removed", pod.ID()) - } - - if err := s.idIndex.Delete(pod.ID()); err != nil { - return errors.Wrapf(err, "error removing pod ID %s from index", pod.ID()) - } - delete(s.pods, pod.ID()) - delete(s.podContainers, pod.ID()) - s.nameIndex.Release(pod.Name()) - - if pod.config.Namespace != "" { - nsIndex, ok := s.namespaceIndexes[pod.config.Namespace] - if !ok { - return errors.Wrapf(define.ErrInternal, "error retrieving index for namespace %q", pod.config.Namespace) - } - if err := nsIndex.idIndex.Delete(pod.ID()); err != nil { - return errors.Wrapf(err, "error removing container %s from namespace ID index", pod.ID()) - } - nsIndex.nameIndex.Release(pod.Name()) - } - - return nil -} - -// RemovePodContainers removes all containers from a pod -// This is used to simultaneously remove a number of containers with -// many interdependencies -// Will only remove containers if no dependencies outside of the pod are present -func (s *InMemoryState) RemovePodContainers(pod *Pod) error { - if !pod.valid { - return errors.Wrapf(define.ErrPodRemoved, "pod %s is not valid", pod.ID()) - } - - if err := s.checkNSMatch(pod.ID(), pod.Namespace()); err != nil { - return err - } - - // Get pod containers - podCtrs, ok := s.podContainers[pod.ID()] - if !ok { - pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "no pod exists in state with ID %s", pod.ID()) - } - - // Go through container dependencies. Check to see if any are outside the pod. - for ctr := range podCtrs { - ctrDeps, ok := s.ctrDepends[ctr] - if ok { - for _, dep := range ctrDeps { - if _, ok := podCtrs[dep]; !ok { - return errors.Wrapf(define.ErrCtrExists, "container %s has dependency %s outside of pod %s", ctr, dep, pod.ID()) - } - } - } - } - - // All dependencies are OK to remove - // Remove all containers - s.podContainers[pod.ID()] = make(map[string]*Container) - for _, ctr := range podCtrs { - if err := s.idIndex.Delete(ctr.ID()); err != nil { - return errors.Wrapf(err, "error removing container ID from index") - } - s.nameIndex.Release(ctr.Name()) - - delete(s.containers, ctr.ID()) - delete(s.ctrDepends, ctr.ID()) - } - - return nil -} - -// AddContainerToPod adds a container to the given pod, also adding it to the -// state -func (s *InMemoryState) AddContainerToPod(pod *Pod, ctr *Container) error { - if !pod.valid { - return errors.Wrapf(define.ErrPodRemoved, "pod %s is not valid", pod.ID()) - } - if !ctr.valid { - return errors.Wrapf(define.ErrCtrRemoved, "container %s is not valid", ctr.ID()) - } - - if ctr.config.Pod != pod.ID() { - return errors.Wrapf(define.ErrInvalidArg, "container %s is not in pod %s", ctr.ID(), pod.ID()) - } - - if ctr.config.Namespace != pod.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %s and pod %s is in namespace %s", - ctr.ID(), ctr.config.Namespace, pod.ID(), pod.config.Namespace) - } - - if err := s.checkNSMatch(ctr.ID(), ctr.Namespace()); err != nil { - return err - } - - // Check networks - for _, net := range ctr.config.Networks { - if net == "" { - return errors.Wrapf(define.ErrInvalidArg, "network names cannot be empty") - } - } - - // Check network aliases - for network := range ctr.config.NetworkAliases { - inNet := false - for _, net := range ctr.config.Networks { - if net == network { - inNet = true - break - } - } - if !inNet { - return errors.Wrapf(define.ErrInvalidArg, "container %s has network aliases for network %q but is not joined to network", ctr.ID(), network) - } - } - - // Retrieve pod containers list - podCtrs, ok := s.podContainers[pod.ID()] - if !ok { - pod.valid = false - return errors.Wrapf(define.ErrPodRemoved, "pod %s not found in state", pod.ID()) - } - - // Is the container already in the pod? - if _, ok = podCtrs[ctr.ID()]; ok { - return errors.Wrapf(define.ErrCtrExists, "container with ID %s already exists in pod %s", ctr.ID(), pod.ID()) - } - - // There are potential race conditions with this - // But in-memory state is intended purely for testing and not production - // use, so this should be fine. - depCtrs := ctr.Dependencies() - for _, depCtr := range depCtrs { - if _, ok = s.containers[depCtr]; !ok { - return errors.Wrapf(define.ErrNoSuchCtr, "cannot depend on nonexistent container %s", depCtr) - } - depCtrStruct, ok := podCtrs[depCtr] - if !ok { - return errors.Wrapf(define.ErrInvalidArg, "cannot depend on container %s as it is not in pod %s", depCtr, pod.ID()) - } - if depCtrStruct.config.Namespace != ctr.config.Namespace { - return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %s and cannot depend on container %s in namespace %s", ctr.ID(), ctr.config.Namespace, depCtr, depCtrStruct.config.Namespace) - } - } - - // Add container to state - if _, ok = s.containers[ctr.ID()]; ok { - return errors.Wrapf(define.ErrCtrExists, "container with ID %s already exists in state", ctr.ID()) - } - - if err := s.nameIndex.Reserve(ctr.Name(), ctr.ID()); err != nil { - return errors.Wrapf(err, "error reserving container name %s", ctr.Name()) - } - - if err := s.idIndex.Add(ctr.ID()); err != nil { - s.nameIndex.Release(ctr.Name()) - return errors.Wrapf(err, "error releasing container ID %s", ctr.ID()) - } - - s.containers[ctr.ID()] = ctr - - // Add container to pod containers - podCtrs[ctr.ID()] = ctr - - // If we're in a namespace, add us to that namespace's indexes - if ctr.config.Namespace != "" { - var nsIndex *namespaceIndex - nsIndex, ok := s.namespaceIndexes[ctr.config.Namespace] - if !ok { - nsIndex = new(namespaceIndex) - nsIndex.nameIndex = registrar.NewRegistrar() - nsIndex.idIndex = truncindex.NewTruncIndex([]string{}) - s.namespaceIndexes[ctr.config.Namespace] = nsIndex - } - // Should be no errors here, the previous index adds should have caught that - if err := nsIndex.nameIndex.Reserve(ctr.Name(), ctr.ID()); err != nil { - return errors.Wrapf(err, "error registering container name %s", ctr.Name()) - } - if err := nsIndex.idIndex.Add(ctr.ID()); err != nil { - return errors.Wrapf(err, "error registering container ID %s", ctr.ID()) - } - } - - // Add containers this container depends on - for _, depCtr := range depCtrs { - s.addCtrToDependsMap(ctr.ID(), depCtr) - } - - // Add container to volume dependencies - for _, vol := range ctr.config.NamedVolumes { - s.addCtrToVolDependsMap(ctr.ID(), vol.Name) - } - - // Add networks - newNets := make([]string, 0, len(ctr.config.Networks)) - for _, net := range ctr.config.Networks { - if net == "" { - return define.ErrInvalidArg - } - newNets = append(newNets, net) - } - s.ctrNetworks[ctr.ID()] = newNets - - // Add network aliases - s.ctrNetworkAliases[ctr.ID()] = ctr.config.NetworkAliases - - return nil -} - -// RemoveContainerFromPod removes the given container from the given pod -// The container is also removed from the state -func (s *InMemoryState) RemoveContainerFromPod(pod *Pod, ctr *Container) error { - if !pod.valid { - return errors.Wrapf(define.ErrPodRemoved, "pod %s is not valid and containers cannot be removed", pod.ID()) - } - if !ctr.valid { - return errors.Wrapf(define.ErrCtrRemoved, "container %s is not valid and cannot be removed from the pod", ctr.ID()) - } - - if err := s.checkNSMatch(ctr.ID(), ctr.Namespace()); err != nil { - return err - } - - // Ensure we don't remove a container which other containers depend on - deps, ok := s.ctrDepends[ctr.ID()] - if ok && len(deps) != 0 { - depsStr := strings.Join(deps, ", ") - return errors.Wrapf(define.ErrDepExists, "the following containers depend on container %s: %s", ctr.ID(), depsStr) - } - - // Ensure we don't have active exec sessions - ctrSessions := s.ctrExecSessions[ctr.ID()] - if len(ctrSessions) > 0 { - sessStr := strings.Join(ctrSessions, ", ") - return errors.Wrapf(define.ErrCtrExists, "the following exec sessions are running for container %s: %s", ctr.ID(), sessStr) - } - - // Retrieve pod containers - podCtrs, ok := s.podContainers[pod.ID()] - if !ok { - pod.valid = false - return errors.Wrapf(define.ErrPodRemoved, "pod %s has been removed", pod.ID()) - } - - // Does the container exist? - if _, ok := s.containers[ctr.ID()]; !ok { - ctr.valid = false - return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in state", ctr.ID()) - } - - // Is the container in the pod? - if _, ok := podCtrs[ctr.ID()]; !ok { - return errors.Wrapf(define.ErrNoSuchCtr, "container with ID %s not found in pod %s", ctr.ID(), pod.ID()) - } - - // Remove container from state - if _, ok := s.containers[ctr.ID()]; !ok { - return errors.Wrapf(define.ErrNoSuchCtr, "no container exists in state with ID %s", ctr.ID()) - } - - if err := s.idIndex.Delete(ctr.ID()); err != nil { - return errors.Wrapf(err, "error removing container ID from index") - } - delete(s.containers, ctr.ID()) - s.nameIndex.Release(ctr.Name()) - - // Remove the container from the pod - delete(podCtrs, ctr.ID()) - - if ctr.config.Namespace != "" { - nsIndex, ok := s.namespaceIndexes[ctr.config.Namespace] - if !ok { - return errors.Wrapf(define.ErrInternal, "error retrieving index for namespace %q", ctr.config.Namespace) - } - if err := nsIndex.idIndex.Delete(ctr.ID()); err != nil { - return errors.Wrapf(err, "error removing container %s from namespace ID index", ctr.ID()) - } - nsIndex.nameIndex.Release(ctr.Name()) - } - - // Remove us from container dependencies - depCtrs := ctr.Dependencies() - for _, depCtr := range depCtrs { - s.removeCtrFromDependsMap(ctr.ID(), depCtr) - } - - // Remove our network aliases - delete(s.ctrNetworkAliases, ctr.ID()) - delete(s.ctrNetworks, ctr.ID()) - - return nil -} - -// UpdatePod updates a pod in the state -// This is a no-op as there is no backing store -func (s *InMemoryState) UpdatePod(pod *Pod) error { - if !pod.valid { - return define.ErrPodRemoved - } - - if err := s.checkNSMatch(pod.ID(), pod.Namespace()); err != nil { - return err - } - - if _, ok := s.pods[pod.ID()]; !ok { - pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "no pod exists in state with ID %s", pod.ID()) - } - - return nil -} - -// SavePod updates a pod in the state -// This is a no-op at there is no backing store -func (s *InMemoryState) SavePod(pod *Pod) error { - if !pod.valid { - return define.ErrPodRemoved - } - - if err := s.checkNSMatch(pod.ID(), pod.Namespace()); err != nil { - return err - } - - if _, ok := s.pods[pod.ID()]; !ok { - pod.valid = false - return errors.Wrapf(define.ErrNoSuchPod, "no pod exists in state with ID %s", pod.ID()) - } - - return nil -} - -// AllPods retrieves all pods currently in the state -func (s *InMemoryState) AllPods() ([]*Pod, error) { - pods := make([]*Pod, 0, len(s.pods)) - for _, pod := range s.pods { - if s.namespace != "" { - if s.namespace == pod.config.Namespace { - pods = append(pods, pod) - } - } else { - pods = append(pods, pod) - } - } - - return pods, nil -} - -// Internal Functions - -// Add a container to the dependency mappings -func (s *InMemoryState) addCtrToDependsMap(ctrID, dependsID string) { - if dependsID != "" { - arr, ok := s.ctrDepends[dependsID] - if !ok { - // Do not have a mapping for that container yet - s.ctrDepends[dependsID] = []string{ctrID} - } else { - // Have a mapping for the container - arr = append(arr, ctrID) - s.ctrDepends[dependsID] = arr - } - } -} - -// Remove a container from dependency mappings -func (s *InMemoryState) removeCtrFromDependsMap(ctrID, dependsID string) { - if dependsID != "" { - arr, ok := s.ctrDepends[dependsID] - if !ok { - // Internal state seems inconsistent - // But the dependency is definitely gone - // So just return - return - } - - newArr := make([]string, 0, len(arr)) - - for _, id := range arr { - if id != ctrID { - newArr = append(newArr, id) - } - } - - s.ctrDepends[dependsID] = newArr - } -} - -// Add a container to the dependency mappings for the volume -func (s *InMemoryState) addCtrToVolDependsMap(depCtrID, volName string) { - if volName != "" { - arr, ok := s.volumeDepends[volName] - if !ok { - // Do not have a mapping for that volume yet - s.volumeDepends[volName] = []string{depCtrID} - } else { - // Have a mapping for the volume - arr = append(arr, depCtrID) - s.volumeDepends[volName] = arr - } - } -} - -// Remove a container from the dependency mappings for the volume -func (s *InMemoryState) removeCtrFromVolDependsMap(depCtrID, volName string) { - if volName != "" { - arr, ok := s.volumeDepends[volName] - if !ok { - // Internal state seems inconsistent - // But the dependency is definitely gone - // So just return - return - } - - newArr := make([]string, 0, len(arr)) - - for _, id := range arr { - if id != depCtrID { - newArr = append(newArr, id) - } - } - - s.volumeDepends[volName] = newArr - } -} - -// Check if we can access a pod or container, or if that is blocked by -// namespaces. -func (s *InMemoryState) checkNSMatch(id, ns string) error { - if s.namespace != "" && s.namespace != ns { - return errors.Wrapf(define.ErrNSMismatch, "cannot access %s as it is in namespace %q and we are in namespace %q", - id, ns, s.namespace) - } - return nil -} diff --git a/libpod/runtime.go b/libpod/runtime.go index 613651790..98ca2d5a4 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -282,11 +282,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) { // package. switch runtime.config.Engine.StateType { case config.InMemoryStateStore: - state, err := NewInMemoryState() - if err != nil { - return err - } - runtime.state = state + return errors.Wrapf(define.ErrInvalidArg, "in-memory state is currently disabled") case config.SQLiteStateStore: return errors.Wrapf(define.ErrInvalidArg, "SQLite state is currently disabled") case config.BoltDBStateStore: diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 537618b65..f9b5c5c51 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -616,20 +616,6 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo } } - // Delete the container. - // Not needed in Configured and Exited states, where the container - // doesn't exist in the runtime - if c.state.State != define.ContainerStateConfigured && - c.state.State != define.ContainerStateExited { - if err := c.delete(ctx); err != nil { - if cleanupErr == nil { - cleanupErr = err - } else { - logrus.Errorf("delete container: %v", err) - } - } - } - // Remove the container from the state if c.config.Pod != "" { // If we're removing the pod, the container will be evicted diff --git a/libpod/state_test.go b/libpod/state_test.go index 559c84d1e..4799d7b8d 100644 --- a/libpod/state_test.go +++ b/libpod/state_test.go @@ -28,8 +28,7 @@ const ( var ( testedStates = map[string]emptyStateFunc{ - "in-memory": getEmptyInMemoryState, - "boltdb": getEmptyBoltState, + "boltdb": getEmptyBoltState, } ) @@ -65,31 +64,6 @@ func getEmptyBoltState() (_ State, _ string, _ lock.Manager, retErr error) { return state, tmpDir, lockManager, nil } -// Get an empty in-memory state for use in tests -func getEmptyInMemoryState() (_ State, _ string, _ lock.Manager, retErr error) { - tmpDir, err := ioutil.TempDir("", tmpDirPrefix) - if err != nil { - return nil, "", nil, err - } - defer func() { - if retErr != nil { - os.RemoveAll(tmpDir) - } - }() - - state, err := NewInMemoryState() - if err != nil { - return nil, "", nil, err - } - - lockManager, err := lock.NewInMemoryManager(16) - if err != nil { - return nil, "", nil, err - } - - return state, tmpDir, lockManager, nil -} - func runForAllStates(t *testing.T, testFunc func(*testing.T, State, lock.Manager)) { for stateName, stateFunc := range testedStates { state, path, manager, err := stateFunc() diff --git a/pkg/registrar/registrar.go b/pkg/registrar/registrar.go deleted file mode 100644 index 1e75ee995..000000000 --- a/pkg/registrar/registrar.go +++ /dev/null @@ -1,127 +0,0 @@ -// Package registrar provides name registration. It reserves a name to a given key. -package registrar - -import ( - "errors" - "sync" -) - -var ( - // ErrNameReserved is an error which is returned when a name is requested to be reserved that already is reserved - ErrNameReserved = errors.New("name is reserved") - // ErrNameNotReserved is an error which is returned when trying to find a name that is not reserved - ErrNameNotReserved = errors.New("name is not reserved") - // ErrNoSuchKey is returned when trying to find the names for a key which is not known - ErrNoSuchKey = errors.New("provided key does not exist") -) - -// Registrar stores indexes a list of keys and their registered names as well as indexes names and the key that they are registered to -// Names must be unique. -// Registrar is safe for concurrent access. -type Registrar struct { - idx map[string][]string - names map[string]string - mu sync.Mutex -} - -// NewRegistrar creates a new Registrar with the an empty index -func NewRegistrar() *Registrar { - return &Registrar{ - idx: make(map[string][]string), - names: make(map[string]string), - } -} - -// Reserve registers a key to a name -// Reserve is idempotent -// Attempting to reserve a key to a name that already exists results in an `ErrNameReserved` -// A name reservation is globally unique -func (r *Registrar) Reserve(name, key string) error { - r.mu.Lock() - defer r.mu.Unlock() - - if k, exists := r.names[name]; exists { - if k != key { - return ErrNameReserved - } - return nil - } - - r.idx[key] = append(r.idx[key], name) - r.names[name] = key - return nil -} - -// Release releases the reserved name -// Once released, a name can be reserved again -func (r *Registrar) Release(name string) { - r.mu.Lock() - defer r.mu.Unlock() - - key, exists := r.names[name] - if !exists { - return - } - - for i, n := range r.idx[key] { - if n != name { - continue - } - r.idx[key] = append(r.idx[key][:i], r.idx[key][i+1:]...) - break - } - - delete(r.names, name) - - if len(r.idx[key]) == 0 { - delete(r.idx, key) - } -} - -// Delete removes all reservations for the passed in key. -// All names reserved to this key are released. -func (r *Registrar) Delete(key string) { - r.mu.Lock() - for _, name := range r.idx[key] { - delete(r.names, name) - } - delete(r.idx, key) - r.mu.Unlock() -} - -// GetNames lists all the reserved names for the given key -func (r *Registrar) GetNames(key string) ([]string, error) { - r.mu.Lock() - defer r.mu.Unlock() - - names, exists := r.idx[key] - if !exists { - return nil, ErrNoSuchKey - } - return names, nil -} - -// Get returns the key that the passed in name is reserved to -func (r *Registrar) Get(name string) (string, error) { - r.mu.Lock() - key, exists := r.names[name] - r.mu.Unlock() - - if !exists { - return "", ErrNameNotReserved - } - return key, nil -} - -// GetAll returns all registered names -func (r *Registrar) GetAll() map[string][]string { - out := make(map[string][]string) - - r.mu.Lock() - // copy index into out - for id, names := range r.idx { - out[id] = names - } - r.mu.Unlock() - return out -} diff --git a/pkg/registrar/registrar_test.go b/pkg/registrar/registrar_test.go deleted file mode 100644 index dc9942e80..000000000 --- a/pkg/registrar/registrar_test.go +++ /dev/null @@ -1,213 +0,0 @@ -package registrar_test - -import ( - "testing" - - "github.com/containers/podman/v3/pkg/registrar" - . "github.com/containers/podman/v3/test/framework" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -// TestRegistrar runs the created specs -func TestRegistrar(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Registrar") -} - -// nolint: gochecknoglobals -var t *TestFramework - -var _ = BeforeSuite(func() { - t = NewTestFramework(NilFunc, NilFunc) - t.Setup() -}) - -var _ = AfterSuite(func() { - t.Teardown() -}) - -// The actual test suite -var _ = t.Describe("Registrar", func() { - // Constant test data needed by some tests - const ( - testKey = "testKey" - testName = "testName" - anotherKey = "anotherKey" - ) - - // The system under test - var sut *registrar.Registrar - - // Prepare the system under test and register a test name and key before - // each test - BeforeEach(func() { - sut = registrar.NewRegistrar() - Expect(sut.Reserve(testName, testKey)).To(BeNil()) - }) - - t.Describe("Reserve", func() { - It("should succeed to reserve a new registrar", func() { - // Given - // When - err := sut.Reserve("name", "key") - - // Then - Expect(err).To(BeNil()) - }) - - It("should succeed to reserve a registrar twice", func() { - // Given - // When - err := sut.Reserve(testName, testKey) - - // Then - Expect(err).To(BeNil()) - }) - - It("should fail to reserve an already reserved registrar", func() { - // Given - // When - err := sut.Reserve(testName, anotherKey) - - // Then - Expect(err).NotTo(BeNil()) - Expect(err).To(Equal(registrar.ErrNameReserved)) - }) - }) - - t.Describe("Release", func() { - It("should succeed to release a registered registrar multiple times", func() { - // Given - // When - // Then - sut.Release(testName) - sut.Release(testName) - }) - - It("should succeed to release a unknown registrar multiple times", func() { - // Given - // When - // Then - sut.Release(anotherKey) - sut.Release(anotherKey) - }) - - It("should succeed to release and re-register a registrar", func() { - // Given - // When - sut.Release(testName) - err := sut.Reserve(testName, testKey) - - // Then - Expect(err).To(BeNil()) - }) - }) - - t.Describe("GetNames", func() { - It("should succeed to retrieve a single name for a registrar", func() { - // Given - // When - names, err := sut.GetNames(testKey) - - // Then - Expect(err).To(BeNil()) - Expect(len(names)).To(Equal(1)) - Expect(names[0]).To(Equal(testName)) - }) - - It("should succeed to retrieve all names for a registrar", func() { - // Given - testNames := []string{"test1", "test2"} - for _, name := range testNames { - Expect(sut.Reserve(name, anotherKey)).To(BeNil()) - } - - // When - names, err := sut.GetNames(anotherKey) - - // Then - Expect(err).To(BeNil()) - Expect(len(names)).To(Equal(2)) - Expect(names).To(Equal(testNames)) - }) - }) - - t.Describe("GetNames", func() { - It("should succeed to retrieve a single name for a registrar", func() { - // Given - // When - names, err := sut.GetNames(testKey) - - // Then - Expect(err).To(BeNil()) - Expect(len(names)).To(Equal(1)) - Expect(names[0]).To(Equal(testName)) - }) - - It("should succeed to retrieve all names for a registrar", func() { - // Given - anotherKey := "anotherKey" - testNames := []string{"test1", "test2"} - for _, name := range testNames { - Expect(sut.Reserve(name, anotherKey)).To(BeNil()) - } - - // When - names, err := sut.GetNames(anotherKey) - - // Then - Expect(err).To(BeNil()) - Expect(len(names)).To(Equal(2)) - Expect(names).To(Equal(testNames)) - }) - }) - - t.Describe("Delete", func() { - It("should succeed to delete a registrar", func() { - // Given - // When - sut.Delete(testKey) - - // Then - names, err := sut.GetNames(testKey) - Expect(len(names)).To(BeZero()) - Expect(err).To(Equal(registrar.ErrNoSuchKey)) - }) - }) - - t.Describe("Get", func() { - It("should succeed to get a key for a registrar", func() { - // Given - // When - key, err := sut.Get(testName) - - // Then - Expect(err).To(BeNil()) - Expect(key).To(Equal(testKey)) - }) - - It("should fail to get a key for a not existing registrar", func() { - // Given - // When - key, err := sut.Get("notExistingName") - - // Then - Expect(key).To(BeEmpty()) - Expect(err).To(Equal(registrar.ErrNameNotReserved)) - }) - }) - - t.Describe("GetAll", func() { - It("should succeed to get all names", func() { - // Given - // When - names := sut.GetAll() - - // Then - Expect(len(names)).To(Equal(1)) - Expect(len(names[testKey])).To(Equal(1)) - Expect(names[testKey][0]).To(Equal(testName)) - }) - }) -}) diff --git a/test/compose/test-compose b/test/compose/test-compose index 7693041ac..abb957b43 100755 --- a/test/compose/test-compose +++ b/test/compose/test-compose @@ -163,18 +163,21 @@ function test_port() { local op="$2" # '=' or '~' local expect="$3" # what to expect from curl output - local actual=$(curl --retry 3 --retry-all-errors -s http://127.0.0.1:$port/) - # The test is flaking with an empty result. The curl retry doesn't solve this. - # If the result is empty sleep one second and try again. - if [[ "$actual" == "" ]]; then + # -s -S means "silent, but show errors" + local actual=$(curl --retry 3 --retry-all-errors -s -S http://127.0.0.1:$port/) + local curl_rc=$? + + # FIXME 2021-04-13: test is flaking, curl succeeds but returns empty result. + # Could it be that the container is not actually ready? Wait, and retry. + if [[ $curl_rc -eq 0 && -z "$actual" ]]; then sleep 1 - local actual=$(curl --retry 3 --retry-all-errors -s http://127.0.0.1:$port/) + echo "# Retrying curl:" + actual=$(curl --retry 3 --retry-all-errors -s -S http://127.0.0.1:$port/) + curl_rc=$? fi - local curl_rc=$? + if [ $curl_rc -ne 0 ]; then _show_ok 0 "$testname - curl failed with status $curl_rc" -### docker-compose down >>$logfile 2>&1 -### exit 1 fi case "$op" in @@ -285,6 +288,10 @@ fi # Too hard to precompute the number of tests; just spit it out at the end. n_tests=0 + +# We aren't really TAP 13; this helps logformatter recognize our output as BATS +echo "TAP version 13" + for t in ${tests_to_run[@]}; do testdir="$(dirname $t)" testname="$(basename $testdir)" diff --git a/test/system/helpers.bash b/test/system/helpers.bash index 823dc3376..b9eacfd0b 100644 --- a/test/system/helpers.bash +++ b/test/system/helpers.bash @@ -9,6 +9,7 @@ PODMAN_TEST_IMAGE_USER=${PODMAN_TEST_IMAGE_USER:-"libpod"} PODMAN_TEST_IMAGE_NAME=${PODMAN_TEST_IMAGE_NAME:-"testimage"} PODMAN_TEST_IMAGE_TAG=${PODMAN_TEST_IMAGE_TAG:-"20210223"} PODMAN_TEST_IMAGE_FQN="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/$PODMAN_TEST_IMAGE_NAME:$PODMAN_TEST_IMAGE_TAG" +PODMAN_TEST_IMAGE_ID= # Remote image that we *DO NOT* fetch or keep by default; used for testing pull # This changed from 0 to 1 on 2021-02-24 due to multiarch considerations; it @@ -53,11 +54,21 @@ function basic_setup() { for line in "${lines[@]}"; do set $line if [ "$1" == "$PODMAN_TEST_IMAGE_FQN" ]; then + if [[ -z "$PODMAN_TEST_IMAGE_ID" ]]; then + # This will probably only trigger the 2nd time through setup + PODMAN_TEST_IMAGE_ID=$2 + fi found_needed_image=1 else - echo "# setup(): removing stray images $1 $2" >&3 + # Always remove image that doesn't match by name + echo "# setup(): removing stray image $1" >&3 run_podman rmi --force "$1" >/dev/null 2>&1 || true - run_podman rmi --force "$2" >/dev/null 2>&1 || true + + # Tagged image will have same IID as our test image; don't rmi it. + if [[ $2 != "$PODMAN_TEST_IMAGE_ID" ]]; then + echo "# setup(): removing stray image $2" >&3 + run_podman rmi --force "$2" >/dev/null 2>&1 || true + fi fi done diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go index 94f2048f3..67f454c9a 100644 --- a/vendor/github.com/containers/common/version/version.go +++ b/vendor/github.com/containers/common/version/version.go @@ -1,4 +1,4 @@ package version // Version is the version of the build. -const Version = "0.35.4" +const Version = "0.36.0" diff --git a/vendor/github.com/containers/ocicrypt/.travis.yml b/vendor/github.com/containers/ocicrypt/.travis.yml index 7031d938a..e4dd4a402 100644 --- a/vendor/github.com/containers/ocicrypt/.travis.yml +++ b/vendor/github.com/containers/ocicrypt/.travis.yml @@ -6,6 +6,7 @@ os: go: - "1.13.x" + - "1.16.x" matrix: include: diff --git a/vendor/github.com/containers/ocicrypt/go.mod b/vendor/github.com/containers/ocicrypt/go.mod index 06a77af95..02be18591 100644 --- a/vendor/github.com/containers/ocicrypt/go.mod +++ b/vendor/github.com/containers/ocicrypt/go.mod @@ -13,9 +13,9 @@ require ( github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 github.com/stretchr/testify v1.3.0 go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 - golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de - golang.org/x/sys v0.0.0-20200817155316-9781c653f443 // indirect + golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 + golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 google.golang.org/grpc v1.33.2 gopkg.in/square/go-jose.v2 v2.5.1 - gopkg.in/yaml.v2 v2.3.0 + gopkg.in/yaml.v2 v2.4.0 ) diff --git a/vendor/github.com/containers/ocicrypt/go.sum b/vendor/github.com/containers/ocicrypt/go.sum index b014b76ee..7153900da 100644 --- a/vendor/github.com/containers/ocicrypt/go.sum +++ b/vendor/github.com/containers/ocicrypt/go.sum @@ -3,7 +3,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -53,8 +52,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -63,21 +62,23 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200817155316-9781c653f443 h1:X18bCaipMcoJGm27Nv7zr4XYPKGUy92GtqboKC2Hxaw= -golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -110,7 +111,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/containers/ocicrypt/gpg.go b/vendor/github.com/containers/ocicrypt/gpg.go index c4d31e52d..b9d55539a 100644 --- a/vendor/github.com/containers/ocicrypt/gpg.go +++ b/vendor/github.com/containers/ocicrypt/gpg.go @@ -27,7 +27,7 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" - "golang.org/x/crypto/ssh/terminal" + "golang.org/x/term" ) // GPGVersion enum representing the GPG client version to use. @@ -387,7 +387,7 @@ func GPGGetPrivateKey(descs []ocispec.Descriptor, gpgClient GPGClient, gpgVault fmt.Printf("Passphrase required for Key id 0x%x: \n%v", keyid, string(keyinfo)) fmt.Printf("Enter passphrase for key with Id 0x%x: ", keyid) - password, err := terminal.ReadPassword(int(os.Stdin.Fd())) + password, err := term.ReadPassword(int(os.Stdin.Fd())) fmt.Printf("\n") if err != nil { return nil, nil, err diff --git a/vendor/github.com/containers/ocicrypt/utils/testing.go b/vendor/github.com/containers/ocicrypt/utils/testing.go index e2ed4b1d8..38633b19b 100644 --- a/vendor/github.com/containers/ocicrypt/utils/testing.go +++ b/vendor/github.com/containers/ocicrypt/utils/testing.go @@ -67,7 +67,7 @@ func CreateRSATestKey(bits int, password []byte, pemencode bool) ([]byte, []byte typ := "RSA PRIVATE KEY" if len(password) > 0 { - block, err = x509.EncryptPEMBlock(rand.Reader, typ, privData, password, x509.PEMCipherAES256) + block, err = x509.EncryptPEMBlock(rand.Reader, typ, privData, password, x509.PEMCipherAES256) //nolint:staticcheck // ignore SA1019, which is kept for backward compatibility if err != nil { return nil, nil, errors.Wrap(err, "x509.EncryptPEMBlock failed") } diff --git a/vendor/github.com/containers/ocicrypt/utils/utils.go b/vendor/github.com/containers/ocicrypt/utils/utils.go index 7bc2aa28d..07fe6d367 100644 --- a/vendor/github.com/containers/ocicrypt/utils/utils.go +++ b/vendor/github.com/containers/ocicrypt/utils/utils.go @@ -95,11 +95,11 @@ func ParsePrivateKey(privKey, privKeyPassword []byte, prefix string) (interface{ block, _ := pem.Decode(privKey) if block != nil { var der []byte - if x509.IsEncryptedPEMBlock(block) { + if x509.IsEncryptedPEMBlock(block) { //nolint:staticcheck // ignore SA1019, which is kept for backward compatibility if privKeyPassword == nil { return nil, errors.Errorf("%s: Missing password for encrypted private key", prefix) } - der, err = x509.DecryptPEMBlock(block, privKeyPassword) + der, err = x509.DecryptPEMBlock(block, privKeyPassword) //nolint:staticcheck // ignore SA1019, which is kept for backward compatibility if err != nil { return nil, errors.Errorf("%s: Wrong password: could not decrypt private key", prefix) } diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go index c474e5a80..94c71ac1a 100644 --- a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go +++ b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.11 && gc && !purego // +build go1.11,gc,!purego package chacha20 diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go index 3e8a609fb..025b49897 100644 --- a/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go +++ b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (!arm64 && !s390x && !ppc64le) || (arm64 && !go1.11) || !gc || purego // +build !arm64,!s390x,!ppc64le arm64,!go1.11 !gc purego package chacha20 diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go index 2806c6325..da420b2e9 100644 --- a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go +++ b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gc && !purego // +build gc,!purego package chacha20 diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go index a0774dde1..c5898db46 100644 --- a/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go +++ b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gc && !purego // +build gc,!purego package chacha20 diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go b/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go index 877b6de29..84858480d 100644 --- a/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go +++ b/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build amd64 && gc && !purego // +build amd64,gc,!purego package curve25519 diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go b/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go index 80d3300af..259728af7 100644 --- a/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go +++ b/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !amd64 || !gc || purego // +build !amd64 !gc purego package curve25519 diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/golang.org/x/crypto/ed25519/ed25519.go index c7f8c7e64..71ad917da 100644 --- a/vendor/golang.org/x/crypto/ed25519/ed25519.go +++ b/vendor/golang.org/x/crypto/ed25519/ed25519.go @@ -5,6 +5,7 @@ // In Go 1.13, the ed25519 package was promoted to the standard library as // crypto/ed25519, and this package became a wrapper for the standard library one. // +//go:build !go1.13 // +build !go1.13 // Package ed25519 implements the Ed25519 signature algorithm. See diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519_go113.go b/vendor/golang.org/x/crypto/ed25519/ed25519_go113.go index d1448d8d2..b5974dc8b 100644 --- a/vendor/golang.org/x/crypto/ed25519/ed25519_go113.go +++ b/vendor/golang.org/x/crypto/ed25519/ed25519_go113.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.13 // +build go1.13 // Package ed25519 implements the Ed25519 signature algorithm. See diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing.go index 281c27ef0..4fad24f8d 100644 --- a/vendor/golang.org/x/crypto/internal/subtle/aliasing.go +++ b/vendor/golang.org/x/crypto/internal/subtle/aliasing.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !purego // +build !purego // Package subtle implements functions that are often useful in cryptographic diff --git a/vendor/golang.org/x/crypto/internal/subtle/aliasing_purego.go b/vendor/golang.org/x/crypto/internal/subtle/aliasing_purego.go index e20a29659..80ccbed2c 100644 --- a/vendor/golang.org/x/crypto/internal/subtle/aliasing_purego.go +++ b/vendor/golang.org/x/crypto/internal/subtle/aliasing_purego.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build purego // +build purego // Package subtle implements functions that are often useful in cryptographic diff --git a/vendor/golang.org/x/crypto/poly1305/bits_compat.go b/vendor/golang.org/x/crypto/poly1305/bits_compat.go index 157a69f61..45b5c966b 100644 --- a/vendor/golang.org/x/crypto/poly1305/bits_compat.go +++ b/vendor/golang.org/x/crypto/poly1305/bits_compat.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !go1.13 // +build !go1.13 package poly1305 diff --git a/vendor/golang.org/x/crypto/poly1305/bits_go1.13.go b/vendor/golang.org/x/crypto/poly1305/bits_go1.13.go index a0a185f0f..ed52b3418 100644 --- a/vendor/golang.org/x/crypto/poly1305/bits_go1.13.go +++ b/vendor/golang.org/x/crypto/poly1305/bits_go1.13.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.13 // +build go1.13 package poly1305 diff --git a/vendor/golang.org/x/crypto/poly1305/mac_noasm.go b/vendor/golang.org/x/crypto/poly1305/mac_noasm.go index af6c94f92..f184b67d9 100644 --- a/vendor/golang.org/x/crypto/poly1305/mac_noasm.go +++ b/vendor/golang.org/x/crypto/poly1305/mac_noasm.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (!amd64 && !ppc64le && !s390x) || !gc || purego // +build !amd64,!ppc64le,!s390x !gc purego package poly1305 diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.go b/vendor/golang.org/x/crypto/poly1305/sum_amd64.go index cf3a69ed3..6d522333f 100644 --- a/vendor/golang.org/x/crypto/poly1305/sum_amd64.go +++ b/vendor/golang.org/x/crypto/poly1305/sum_amd64.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gc && !purego // +build gc,!purego package poly1305 diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go b/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go index cb4b7185d..4a069941a 100644 --- a/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go +++ b/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gc && !purego // +build gc,!purego package poly1305 diff --git a/vendor/golang.org/x/crypto/poly1305/sum_s390x.go b/vendor/golang.org/x/crypto/poly1305/sum_s390x.go index 188a665e1..62cc9f847 100644 --- a/vendor/golang.org/x/crypto/poly1305/sum_s390x.go +++ b/vendor/golang.org/x/crypto/poly1305/sum_s390x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gc && !purego // +build gc,!purego package poly1305 diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go index 2aa859f76..e125bbd2a 100644 --- a/vendor/golang.org/x/net/http2/server.go +++ b/vendor/golang.org/x/net/http2/server.go @@ -1293,7 +1293,9 @@ func (sc *serverConn) startGracefulShutdown() { sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) }) } -// After sending GOAWAY, the connection will close after goAwayTimeout. +// After sending GOAWAY with an error code (non-graceful shutdown), the +// connection will close after goAwayTimeout. +// // If we close the connection immediately after sending GOAWAY, there may // be unsent data in our kernel receive buffer, which will cause the kernel // to send a TCP RST on close() instead of a FIN. This RST will abort the @@ -1629,23 +1631,37 @@ func (sc *serverConn) processSettingInitialWindowSize(val uint32) error { func (sc *serverConn) processData(f *DataFrame) error { sc.serveG.check() - if sc.inGoAway && sc.goAwayCode != ErrCodeNo { + id := f.Header().StreamID + if sc.inGoAway && (sc.goAwayCode != ErrCodeNo || id > sc.maxClientStreamID) { + // Discard all DATA frames if the GOAWAY is due to an + // error, or: + // + // Section 6.8: After sending a GOAWAY frame, the sender + // can discard frames for streams initiated by the + // receiver with identifiers higher than the identified + // last stream. return nil } - data := f.Data() - // "If a DATA frame is received whose stream is not in "open" - // or "half closed (local)" state, the recipient MUST respond - // with a stream error (Section 5.4.2) of type STREAM_CLOSED." - id := f.Header().StreamID + data := f.Data() state, st := sc.state(id) if id == 0 || state == stateIdle { + // Section 6.1: "DATA frames MUST be associated with a + // stream. If a DATA frame is received whose stream + // identifier field is 0x0, the recipient MUST respond + // with a connection error (Section 5.4.1) of type + // PROTOCOL_ERROR." + // // Section 5.1: "Receiving any frame other than HEADERS // or PRIORITY on a stream in this state MUST be // treated as a connection error (Section 5.4.1) of // type PROTOCOL_ERROR." return ConnectionError(ErrCodeProtocol) } + + // "If a DATA frame is received whose stream is not in "open" + // or "half closed (local)" state, the recipient MUST respond + // with a stream error (Section 5.4.2) of type STREAM_CLOSED." if st == nil || state != stateOpen || st.gotTrailerHeader || st.resetQueued { // This includes sending a RST_STREAM if the stream is // in stateHalfClosedLocal (which currently means that diff --git a/vendor/modules.txt b/vendor/modules.txt index 0f8b515e2..1bf189b86 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -93,7 +93,7 @@ github.com/containers/buildah/pkg/parse github.com/containers/buildah/pkg/rusage github.com/containers/buildah/pkg/supplemented github.com/containers/buildah/util -# github.com/containers/common v0.35.4 +# github.com/containers/common v0.36.0 github.com/containers/common/pkg/apparmor github.com/containers/common/pkg/apparmor/internal/supported github.com/containers/common/pkg/auth @@ -163,7 +163,7 @@ github.com/containers/image/v5/types github.com/containers/image/v5/version # github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b github.com/containers/libtrust -# github.com/containers/ocicrypt v1.1.0 +# github.com/containers/ocicrypt v1.1.1 github.com/containers/ocicrypt github.com/containers/ocicrypt/blockcipher github.com/containers/ocicrypt/config @@ -619,7 +619,7 @@ go.opencensus.io/internal go.opencensus.io/trace go.opencensus.io/trace/internal go.opencensus.io/trace/tracestate -# golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad +# golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 golang.org/x/crypto/blowfish golang.org/x/crypto/cast5 golang.org/x/crypto/chacha20 @@ -640,7 +640,7 @@ golang.org/x/crypto/ssh/agent golang.org/x/crypto/ssh/internal/bcrypt_pbkdf golang.org/x/crypto/ssh/knownhosts golang.org/x/crypto/ssh/terminal -# golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 +# golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 golang.org/x/net/context golang.org/x/net/html golang.org/x/net/html/atom |