diff options
-rw-r--r-- | cmd/podman/login.go | 14 | ||||
-rw-r--r-- | cmd/podman/logout.go | 12 | ||||
-rw-r--r-- | docs/source/markdown/podman-login.1.md | 7 | ||||
-rw-r--r-- | docs/source/markdown/podman-logout.1.md | 3 | ||||
-rw-r--r-- | pkg/api/handlers/generic/images.go | 50 | ||||
-rw-r--r-- | pkg/api/handlers/utils/containers.go | 2 | ||||
-rw-r--r-- | test/e2e/login_logout_test.go | 52 |
7 files changed, 98 insertions, 42 deletions
diff --git a/cmd/podman/login.go b/cmd/podman/login.go index 369e0da16..e5ff273b8 100644 --- a/cmd/podman/login.go +++ b/cmd/podman/login.go @@ -12,6 +12,7 @@ import ( "github.com/containers/image/v5/types" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/pkg/registries" "github.com/docker/docker-credential-helpers/credentials" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -67,10 +68,19 @@ func loginCmd(c *cliconfig.LoginValues) error { if len(args) > 1 { return errors.Errorf("too many arguments, login takes only 1 argument") } + var server string if len(args) == 0 { - return errors.Errorf("please specify a registry to login to") + registriesFromFile, err := registries.GetRegistries() + if err != nil || len(registriesFromFile) == 0 { + return errors.Errorf("please specify a registry to login to") + } + + server = registriesFromFile[0] + logrus.Debugf("registry not specified, default to the first registry %q from registries.conf", server) + + } else { + server = registryFromFullName(scrubServer(args[0])) } - server := registryFromFullName(scrubServer(args[0])) sc := image.GetSystemContext("", c.Authfile, false) if c.Flag("tls-verify").Changed { diff --git a/cmd/podman/logout.go b/cmd/podman/logout.go index 4a113b1d0..dec6822cf 100644 --- a/cmd/podman/logout.go +++ b/cmd/podman/logout.go @@ -8,7 +8,9 @@ import ( "github.com/containers/image/v5/pkg/docker/config" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/shared" + "github.com/containers/libpod/pkg/registries" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -51,10 +53,16 @@ func logoutCmd(c *cliconfig.LogoutValues) error { if len(args) > 1 { return errors.Errorf("too many arguments, logout takes at most 1 argument") } + var server string if len(args) == 0 && !c.All { - return errors.Errorf("registry must be given") + registriesFromFile, err := registries.GetRegistries() + if err != nil || len(registriesFromFile) == 0 { + return errors.Errorf("no registries found in registries.conf, a registry must be provided") + } + + server = registriesFromFile[0] + logrus.Debugf("registry not specified, default to the first registry %q from registries.conf", server) } - var server string if len(args) == 1 { server = scrubServer(args[0]) } diff --git a/docs/source/markdown/podman-login.1.md b/docs/source/markdown/podman-login.1.md index 8a84d359d..a69b311eb 100644 --- a/docs/source/markdown/podman-login.1.md +++ b/docs/source/markdown/podman-login.1.md @@ -4,11 +4,12 @@ podman\-login - Login to a container registry ## SYNOPSIS -**podman login** [*options*] *registry* +**podman login** [*options*] [*registry*] ## DESCRIPTION **podman login** logs into a specified registry server with the correct username -and password. **podman login** reads in the username and password from STDIN. +and password. If the registry is not specified, the first registry under [registries.search] +from registries.conf will be used. **podman login** reads in the username and password from STDIN. The username and password can also be set using the **username** and **password** flags. The path of the authentication file can be specified by the user by setting the **authfile** flag. The default path used is **${XDG\_RUNTIME\_DIR}/containers/auth.json**. @@ -17,7 +18,7 @@ flag. The default path used is **${XDG\_RUNTIME\_DIR}/containers/auth.json**. **podman login [GLOBAL OPTIONS]** -**podman login [OPTIONS] REGISTRY [GLOBAL OPTIONS]** +**podman login [OPTIONS] [REGISTRY] [GLOBAL OPTIONS]** ## OPTIONS diff --git a/docs/source/markdown/podman-logout.1.md b/docs/source/markdown/podman-logout.1.md index 01dc52ecd..8b9f75760 100644 --- a/docs/source/markdown/podman-logout.1.md +++ b/docs/source/markdown/podman-logout.1.md @@ -8,7 +8,8 @@ podman\-logout - Logout of a container registry ## DESCRIPTION **podman logout** logs out of a specified registry server by deleting the cached credentials -stored in the **auth.json** file. The path of the authentication file can be overridden by the user by setting the **authfile** flag. +stored in the **auth.json** file. If the registry is not specified, the first registry under [registries.search] +from registries.conf will be used. The path of the authentication file can be overridden by the user by setting the **authfile** flag. The default path used is **${XDG\_RUNTIME\_DIR}/containers/auth.json**. All the cached credentials can be removed by setting the **all** flag. diff --git a/pkg/api/handlers/generic/images.go b/pkg/api/handlers/generic/images.go index c65db7575..afd107207 100644 --- a/pkg/api/handlers/generic/images.go +++ b/pkg/api/handlers/generic/images.go @@ -106,14 +106,14 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) query := struct { - author string - changes string - comment string - container string + Author string `schema:"author"` + Changes string `schema:"changes"` + Comment string `schema:"comment"` + Container string `schema:"container"` //fromSrc string # fromSrc is currently unused - pause bool - repo string - tag string + Pause bool `schema:"pause"` + Repo string `schema:"repo"` + Tag string `schema:"tag"` }{ // This is where you can override the golang default value for one of fields } @@ -145,22 +145,22 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) { return } - if len(query.tag) > 0 { - tag = query.tag + if len(query.Tag) > 0 { + tag = query.Tag } - options.Message = query.comment - options.Author = query.author - options.Pause = query.pause - options.Changes = strings.Fields(query.changes) - ctr, err := runtime.LookupContainer(query.container) + options.Message = query.Comment + options.Author = query.Author + options.Pause = query.Pause + options.Changes = strings.Fields(query.Changes) + ctr, err := runtime.LookupContainer(query.Container) if err != nil { utils.Error(w, "Something went wrong.", http.StatusNotFound, err) return } // I know mitr hates this ... but doing for now - if len(query.repo) > 1 { - destImage = fmt.Sprintf("%s:%s", query.repo, tag) + if len(query.Repo) > 1 { + destImage = fmt.Sprintf("%s:%s", query.Repo, tag) } commitImage, err := ctr.Commit(r.Context(), destImage, options) @@ -179,8 +179,8 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) query := struct { - fromSrc string - changes []string + FromSrc string `schema:"fromSrc"` + Changes []string `schema:"changes"` }{ // This is where you can override the golang default value for one of fields } @@ -190,7 +190,7 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { return } // fromSrc – Source to import. The value may be a URL from which the image can be retrieved or - to read the image from the request body. This parameter may only be used when importing an image. - source := query.fromSrc + source := query.FromSrc if source == "-" { f, err := ioutil.TempFile("", "api_load.tar") if err != nil { @@ -202,7 +202,7 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file")) } } - iid, err := runtime.Import(r.Context(), source, "", query.changes, "", false) + iid, err := runtime.Import(r.Context(), source, "", query.Changes, "", false) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to import tarball")) return @@ -238,8 +238,8 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) query := struct { - fromImage string - tag string + FromImage string `schema:"fromImage"` + Tag string `schema:"tag"` }{ // This is where you can override the golang default value for one of fields } @@ -254,9 +254,9 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) { repo – Repository name given to an image when it is imported. The repo may include a tag. This parameter may only be used when importing an image. tag – Tag or digest. If empty when pulling an image, this causes all tags for the given image to be pulled. */ - fromImage := query.fromImage - if len(query.tag) < 1 { - fromImage = fmt.Sprintf("%s:%s", fromImage, query.tag) + fromImage := query.FromImage + if len(query.Tag) < 1 { + fromImage = fmt.Sprintf("%s:%s", fromImage, query.Tag) } // TODO diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go index 74485edf2..c9bb9cf09 100644 --- a/pkg/api/handlers/utils/containers.go +++ b/pkg/api/handlers/utils/containers.go @@ -15,7 +15,7 @@ import ( func KillContainer(w http.ResponseWriter, r *http.Request) (*libpod.Container, error) { runtime := r.Context().Value("runtime").(*libpod.Runtime) - decoder := r.Context().Value("decorder").(*schema.Decoder) + decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { Signal syscall.Signal `schema:"signal"` }{ diff --git a/test/e2e/login_logout_test.go b/test/e2e/login_logout_test.go index 78c9b52d9..42698d270 100644 --- a/test/e2e/login_logout_test.go +++ b/test/e2e/login_logout_test.go @@ -19,14 +19,15 @@ import ( var _ = Describe("Podman login and logout", func() { var ( - tempdir string - err error - podmanTest *PodmanTestIntegration - authPath string - certPath string - port int - server string - testImg string + tempdir string + err error + podmanTest *PodmanTestIntegration + authPath string + certPath string + port int + server string + testImg string + registriesConfWithSearch []byte ) BeforeEach(func() { @@ -64,6 +65,9 @@ var _ = Describe("Podman login and logout", func() { f.Sync() port = 4999 + config.GinkgoConfig.ParallelNode server = strings.Join([]string{"localhost", strconv.Itoa(port)}, ":") + + registriesConfWithSearch = []byte(fmt.Sprintf("[registries.search]\nregistries = ['%s']", server)) + testImg = strings.Join([]string{server, "test-apline"}, "/") os.MkdirAll(filepath.Join("/etc/containers/certs.d", server), os.ModePerm) @@ -113,6 +117,38 @@ var _ = Describe("Podman login and logout", func() { Expect(session).To(ExitWithError()) }) + It("podman login and logout without registry parameter", func() { + SkipIfRootless() + + registriesConf, err := ioutil.TempFile("", "TestLoginWithoutParameter") + Expect(err).To(BeNil()) + defer registriesConf.Close() + defer os.Remove(registriesConf.Name()) + + err = ioutil.WriteFile(registriesConf.Name(), []byte(registriesConfWithSearch), os.ModePerm) + Expect(err).To(BeNil()) + + // Environment is per-process, so this looks very unsafe; actually it seems fine because tests are not + // run in parallel unless they opt in by calling t.Parallel(). So don’t do that. + oldRCP, hasRCP := os.LookupEnv("REGISTRIES_CONFIG_PATH") + defer func() { + if hasRCP { + os.Setenv("REGISTRIES_CONFIG_PATH", oldRCP) + } else { + os.Unsetenv("REGISTRIES_CONFIG_PATH") + } + }() + os.Setenv("REGISTRIES_CONFIG_PATH", registriesConf.Name()) + + session := podmanTest.Podman([]string{"login", "-u", "podmantest", "-p", "test"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To((Equal(0))) + + session = podmanTest.Podman([]string{"logout"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) + It("podman login and logout with flag --authfile", func() { SkipIfRootless() authFile := filepath.Join(podmanTest.TempDir, "auth.json") |