diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/boltdb_state.go | 167 | ||||
-rw-r--r-- | libpod/container_internal.go | 20 | ||||
-rw-r--r-- | libpod/container_internal_test.go | 48 | ||||
-rw-r--r-- | libpod/oci.go | 6 |
4 files changed, 172 insertions, 69 deletions
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index c226a0617..92a7b1538 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -382,6 +382,11 @@ func (s *BoltState) LookupContainer(idOrName string) (*Container, error) { return err } + namesBucket, err := getNamesBucket(tx) + if err != nil { + return err + } + nsBucket, err := getNSBucket(tx) if err != nil { return err @@ -395,41 +400,59 @@ func (s *BoltState) LookupContainer(idOrName string) (*Container, error) { // It might not be in our namespace, but // getContainerFromDB() will handle that case. id = []byte(idOrName) - } else { - // They did not give us a full container ID. - // Search for partial ID or full name matches - // Use else-if in case the name is set to a partial ID - exists := false - err = idBucket.ForEach(func(checkID, checkName []byte) error { - // If the container isn't in our namespace, we - // can't match it - if s.namespaceBytes != nil { - ns := nsBucket.Get(checkID) - if !bytes.Equal(ns, s.namespaceBytes) { - return nil - } + return s.getContainerFromDB(id, ctr, ctrBucket) + } + + // Next, check if the full name was given + isPod := false + fullID := namesBucket.Get([]byte(idOrName)) + if fullID != nil { + // The name exists and maps to an ID. + // However, we are not yet certain the ID is a + // container. + ctrExists = ctrBucket.Bucket(fullID) + if ctrExists != nil { + // A container bucket matching the full ID was + // found. + return s.getContainerFromDB(fullID, ctr, ctrBucket) + } + // Don't error if we have a name match but it's not a + // container - there's a chance we have a container with + // an ID starting with those characters. + // However, so we can return a good error, note whether + // this is a pod. + isPod = true + } + + // We were not given a full container ID or name. + // Search for partial ID matches. + exists := false + err = idBucket.ForEach(func(checkID, checkName []byte) error { + // If the container isn't in our namespace, we + // can't match it + if s.namespaceBytes != nil { + ns := nsBucket.Get(checkID) + if !bytes.Equal(ns, s.namespaceBytes) { + return nil } - if string(checkName) == idOrName { - if exists { - return errors.Wrapf(ErrCtrExists, "more than one result for ID or name %s", idOrName) - } - id = checkID - exists = true - } else if strings.HasPrefix(string(checkID), idOrName) { - if exists { - return errors.Wrapf(ErrCtrExists, "more than one result for ID or name %s", idOrName) - } - id = checkID - exists = true + } + if strings.HasPrefix(string(checkID), idOrName) { + if exists { + return errors.Wrapf(ErrCtrExists, "more than one result for container ID %s", idOrName) } + id = checkID + exists = true + } - return nil - }) - if err != nil { - return err - } else if !exists { - return errors.Wrapf(ErrNoSuchCtr, "no container with name or ID %s found", idOrName) + return nil + }) + if err != nil { + return err + } else if !exists { + if isPod { + return errors.Wrapf(ErrNoSuchCtr, "%s is a pod, not a container", idOrName) } + return errors.Wrapf(ErrNoSuchCtr, "no container with name or ID %s found", idOrName) } return s.getContainerFromDB(id, ctr, ctrBucket) @@ -941,6 +964,11 @@ func (s *BoltState) LookupPod(idOrName string) (*Pod, error) { return err } + namesBkt, err := getNamesBucket(tx) + if err != nil { + return err + } + nsBkt, err := getNSBucket(tx) if err != nil { return err @@ -954,41 +982,56 @@ func (s *BoltState) LookupPod(idOrName string) (*Pod, error) { // It might not be in our namespace, but getPodFromDB() // will handle that case. id = []byte(idOrName) - } else { - // They did not give us a full pod ID. - // Search for partial ID or full name matches - // Use else-if in case the name is set to a partial ID - exists := false - err = idBucket.ForEach(func(checkID, checkName []byte) error { - // If the pod isn't in our namespace, we - // can't match it - if s.namespaceBytes != nil { - ns := nsBkt.Get(checkID) - if !bytes.Equal(ns, s.namespaceBytes) { - return nil - } + return s.getPodFromDB(id, pod, podBkt) + } + + // Next, check if the full name was given + isCtr := false + fullID := namesBkt.Get([]byte(idOrName)) + if fullID != nil { + // The name exists and maps to an ID. + // However, we aren't yet sure if the ID is a pod. + podExists = podBkt.Bucket(fullID) + if podExists != nil { + // A pod bucket matching the full ID was found. + return s.getPodFromDB(fullID, pod, podBkt) + } + // Don't error if we have a name match but it's not a + // pod - there's a chance we have a pod with an ID + // starting with those characters. + // However, so we can return a good error, note whether + // this is a container. + isCtr = true + } + // They did not give us a full pod name or ID. + // Search for partial ID matches. + exists := false + err = idBucket.ForEach(func(checkID, checkName []byte) error { + // If the pod isn't in our namespace, we + // can't match it + if s.namespaceBytes != nil { + ns := nsBkt.Get(checkID) + if !bytes.Equal(ns, s.namespaceBytes) { + return nil } - if string(checkName) == idOrName { - if exists { - return errors.Wrapf(ErrPodExists, "more than one result for ID or name %s", idOrName) - } - id = checkID - exists = true - } else if strings.HasPrefix(string(checkID), idOrName) { - if exists { - return errors.Wrapf(ErrPodExists, "more than one result for ID or name %s", idOrName) - } - id = checkID - exists = true + } + if strings.HasPrefix(string(checkID), idOrName) { + if exists { + return errors.Wrapf(ErrPodExists, "more than one result for ID or name %s", idOrName) } + id = checkID + exists = true + } - return nil - }) - if err != nil { - return err - } else if !exists { - return errors.Wrapf(ErrNoSuchPod, "no pod with name or ID %s found", idOrName) + return nil + }) + if err != nil { + return err + } else if !exists { + if isCtr { + return errors.Wrapf(ErrNoSuchPod, "%s is a container, not a pod", idOrName) } + return errors.Wrapf(ErrNoSuchPod, "no pod with name or ID %s found", idOrName) } // We might have found a container ID, but it's OK diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 08945c410..d86062e38 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -34,8 +34,8 @@ const ( ) var ( - // localeToLanguage maps from locale values to language tags. - localeToLanguage = map[string]string{ + // localeToLanguageMap maps from locale values to language tags. + localeToLanguageMap = map[string]string{ "": "und-u-va-posix", "c": "und-u-va-posix", "posix": "und-u-va-posix", @@ -1281,6 +1281,16 @@ func (c *Container) saveSpec(spec *spec.Spec) error { return nil } +// localeToLanguage translates POSIX locale strings to BCP 47 language tags. +func localeToLanguage(locale string) string { + locale = strings.Replace(strings.SplitN(locale, ".", 2)[0], "_", "-", 1) + langString, ok := localeToLanguageMap[strings.ToLower(locale)] + if !ok { + langString = locale + } + return langString +} + // 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 @@ -1296,11 +1306,7 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (exten } } - langString, ok := localeToLanguage[strings.ToLower(locale)] - if !ok { - langString = locale - } - + langString := localeToLanguage(locale) lang, err := language.Parse(langString) if err != nil { logrus.Warnf("failed to parse language %q: %s", langString, err) diff --git a/libpod/container_internal_test.go b/libpod/container_internal_test.go index f1e2b70a7..1654af929 100644 --- a/libpod/container_internal_test.go +++ b/libpod/container_internal_test.go @@ -17,6 +17,54 @@ import ( // hookPath is the path to an example hook executable. var hookPath string +func TestLocaleToLanguage(t *testing.T) { + for _, testCase := range []struct { + locale string + language string + }{ + { + locale: "", + language: "und-u-va-posix", + }, + { + locale: "C", + language: "und-u-va-posix", + }, + { + locale: "POSIX", + language: "und-u-va-posix", + }, + { + locale: "c", + language: "und-u-va-posix", + }, + { + locale: "en", + language: "en", + }, + { + locale: "en_US", + language: "en-US", + }, + { + locale: "en.UTF-8", + language: "en", + }, + { + locale: "en_US.UTF-8", + language: "en-US", + }, + { + locale: "does-not-exist", + language: "does-not-exist", + }, + } { + t.Run(testCase.locale, func(t *testing.T) { + assert.Equal(t, testCase.language, localeToLanguage(testCase.locale)) + }) + } +} + func TestPostDeleteHooks(t *testing.T) { ctx := context.Background() dir, err := ioutil.TempDir("", "libpod_test_") diff --git a/libpod/oci.go b/libpod/oci.go index 2cbf25699..c3b5f9af2 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -805,6 +805,12 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty execCmd.Env = append(execCmd.Env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)) + if preserveFDs > 0 { + for fd := 3; fd < 3+preserveFDs; fd++ { + execCmd.ExtraFiles = append(execCmd.ExtraFiles, os.NewFile(uintptr(fd), fmt.Sprintf("fd-%d", fd))) + } + } + if err := execCmd.Start(); err != nil { return nil, errors.Wrapf(err, "cannot start container %s", c.ID()) } |