diff options
-rw-r--r-- | go.mod | 2 | ||||
-rw-r--r-- | go.sum | 4 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 20 | ||||
-rw-r--r-- | libpod/container_log.go | 54 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images.go | 34 | ||||
-rw-r--r-- | pkg/api/handlers/compat/networks.go | 33 | ||||
-rw-r--r-- | pkg/api/handlers/compat/swagger.go | 7 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/images_pull.go | 2 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/networks.go | 3 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/swagger.go | 7 | ||||
-rw-r--r-- | pkg/api/server/register_images.go | 20 | ||||
-rw-r--r-- | pkg/api/server/register_networks.go | 19 | ||||
-rw-r--r-- | test/apiv2/python/rest_api/test_v2_0_0_image.py | 5 | ||||
-rw-r--r-- | test/apiv2/python/rest_api/test_v2_0_0_network.py | 27 | ||||
-rw-r--r-- | test/e2e/logs_test.go | 14 | ||||
-rw-r--r-- | vendor/github.com/containers/buildah/CHANGELOG.md | 3 | ||||
-rw-r--r-- | vendor/github.com/containers/buildah/changelog.txt | 3 | ||||
-rw-r--r-- | vendor/github.com/containers/buildah/define/types.go | 2 | ||||
-rw-r--r-- | vendor/modules.txt | 2 |
19 files changed, 186 insertions, 75 deletions
@@ -11,7 +11,7 @@ require ( github.com/container-orchestrated-devices/container-device-interface v0.0.0-20210325223243-f99e8b6c10b9 github.com/containernetworking/cni v0.8.1 github.com/containernetworking/plugins v0.9.1 - github.com/containers/buildah v1.21.0 + github.com/containers/buildah v1.21.1 github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a github.com/containers/conmon v2.0.20+incompatible github.com/containers/image/v5 v5.12.0 @@ -218,8 +218,8 @@ github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHV github.com/containernetworking/plugins v0.8.7/go.mod h1:R7lXeZaBzpfqapcAbHRW8/CYwm0dHzbz0XEjofx0uB0= github.com/containernetworking/plugins v0.9.1 h1:FD1tADPls2EEi3flPc2OegIY1M9pUa9r2Quag7HMLV8= github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containers/buildah v1.21.0 h1:LuwuqRPjan3X3AIdGwfkEkqMgmrDMNpQznFqNdHgCz8= -github.com/containers/buildah v1.21.0/go.mod h1:yPdlpVd93T+i91yGxrJbW1YOWrqN64j5ZhHOZmHUejs= +github.com/containers/buildah v1.21.1 h1:e9LmTCUKUBLg72v5DnIOT/wc8ffkfB7LbpQBywLZo20= +github.com/containers/buildah v1.21.1/go.mod h1:yPdlpVd93T+i91yGxrJbW1YOWrqN64j5ZhHOZmHUejs= github.com/containers/common v0.38.4/go.mod h1:egfpX/Y3+19Dz4Wa1eRZDdgzoEOeneieF9CQppKzLBg= github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a h1:XzYOUf7qjgVJ59YGqAzehlbT63EgjUJhMnfhsPSSJV0= github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a/go.mod h1:CxHAf4iQOZZ8nASIjMdYHHRyA8dMR4tINSS7WQWlv90= diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index a3acc3198..94bf7855b 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -1650,22 +1650,20 @@ func (c *Container) generateResolvConf() (string, error) { } } - // Determine the endpoint for resolv.conf in case it is a symlink - resolvPath, err := filepath.EvalSymlinks(resolvConf) + contents, err := ioutil.ReadFile(resolvConf) // resolv.conf doesn't have to exists if err != nil && !os.IsNotExist(err) { return "", err } - // Determine if symlink points to any of the systemd-resolved files - if strings.HasPrefix(resolvPath, "/run/systemd/resolve/") { - resolvPath = "/run/systemd/resolve/resolv.conf" - } - - contents, err := ioutil.ReadFile(resolvPath) - // resolv.conf doesn't have to exists - if err != nil && !os.IsNotExist(err) { - return "", err + ns := resolvconf.GetNameservers(contents) + // check if systemd-resolved is used, assume it is used when 127.0.0.53 is the only nameserver + if len(ns) == 1 && ns[0] == "127.0.0.53" { + // read the actual resolv.conf file for systemd-resolved + contents, err = ioutil.ReadFile("/run/systemd/resolve/resolv.conf") + if err != nil { + return "", errors.Wrapf(err, "detected that systemd-resolved is in use, but could not locate real resolv.conf") + } } ipv6 := false diff --git a/libpod/container_log.go b/libpod/container_log.go index c207df819..a30e4f5cc 100644 --- a/libpod/container_log.go +++ b/libpod/container_log.go @@ -4,11 +4,10 @@ import ( "context" "fmt" "os" - "time" "github.com/containers/podman/v3/libpod/define" + "github.com/containers/podman/v3/libpod/events" "github.com/containers/podman/v3/libpod/logs" - "github.com/hpcloud/tail/watch" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -94,27 +93,40 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption }() // Check if container is still running or paused if options.Follow { + state, err := c.State() + if err != nil || state != define.ContainerStateRunning { + // If the container isn't running or if we encountered + // an error getting its state, instruct the logger to + // read the file until EOF. + tailError := t.StopAtEOF() + if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" { + logrus.Error(tailError) + } + if errors.Cause(err) != define.ErrNoSuchCtr { + logrus.Error(err) + } + return nil + } + + // The container is running, so we need to wait until the container exited go func() { - for { - state, err := c.State() - time.Sleep(watch.POLL_DURATION) - if err != nil { - tailError := t.StopAtEOF() - if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" { - logrus.Error(tailError) - } - if errors.Cause(err) != define.ErrNoSuchCtr { - logrus.Error(err) - } - break - } - if state != define.ContainerStateRunning && state != define.ContainerStatePaused { - tailError := t.StopAtEOF() - if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" { - logrus.Error(tailError) - } - break + eventChannel := make(chan *events.Event) + eventOptions := events.ReadOptions{ + EventChannel: eventChannel, + Filters: []string{"event=died", "container=" + c.ID()}, + Stream: true, + } + go func() { + if err := c.runtime.Events(ctx, eventOptions); err != nil { + logrus.Errorf("Error waiting for container to exit: %v", err) } + }() + // Now wait for the died event and signal to finish + // reading the log until EOF. + <-eventChannel + tailError := t.StopAtEOF() + if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" { + logrus.Error(tailError) } }() } diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go index 7b336c470..ac212474b 100644 --- a/pkg/api/handlers/compat/images.go +++ b/pkg/api/handlers/compat/images.go @@ -168,6 +168,8 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { query := struct { FromSrc string `schema:"fromSrc"` Changes []string `schema:"changes"` + Message string `schema:"message"` + Repo string `shchema:"repo"` }{ // This is where you can override the golang default value for one of fields } @@ -184,14 +186,15 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to create tempfile")) return } + source = f.Name() if err := SaveFromBody(f, r); err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file")) } } - imageEngine := abi.ImageEngine{Libpod: runtime} - report, err := imageEngine.Import(r.Context(), entities.ImageImportOptions{Source: source, Changes: query.Changes}) + // TODO: add support for ImageImportOptions to take a platform parameter. Also import https://github.com/opencontainers/image-spec/tree/master/specs-go/v1 either here or within imageEngine.Import to get default platform + report, err := imageEngine.Import(r.Context(), entities.ImageImportOptions{Source: source, Changes: query.Changes, Message: query.Message, Reference: query.Repo}) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to import tarball")) return @@ -224,10 +227,10 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) { query := struct { FromImage string `schema:"fromImage"` Tag string `schema:"tag"` + Platform string `schema:"platform"` }{ // This is where you can override the golang default value for one of fields } - if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) return @@ -250,12 +253,36 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) { } defer auth.RemoveAuthfile(authfile) + platformSpecs := strings.Split(query.Platform, "/") // split query into its parts + + addOS := true // default assume true due to structure of if/else below + addArch := false + addVariant := false + + if len(platformSpecs) > 1 { // if we have two arguments then we have os and arch + addArch = true + if len(platformSpecs) > 2 { // if we have 3 arguments then we have os arch and variant + addVariant = true + } + } else if len(platformSpecs) == 0 { + addOS = false + } + pullOptions := &libimage.PullOptions{} pullOptions.AuthFilePath = authfile if authConf != nil { pullOptions.Username = authConf.Username pullOptions.Password = authConf.Password pullOptions.IdentityToken = authConf.IdentityToken + if addOS { // if the len is not 0 + pullOptions.OS = platformSpecs[0] + if addArch { + pullOptions.Architecture = platformSpecs[1] + } + if addVariant { + pullOptions.Variant = platformSpecs[2] + } + } } pullOptions.Writer = os.Stderr // allows for debugging on the server @@ -294,7 +321,6 @@ loop: // break out of for/select infinite loop Error string `json:"error,omitempty"` Id string `json:"id,omitempty"` // nolint } - select { case e := <-progress: switch e.Event { diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go index 77ed548d8..4e1f31404 100644 --- a/pkg/api/handlers/compat/networks.go +++ b/pkg/api/handlers/compat/networks.go @@ -28,19 +28,24 @@ import ( func InspectNetwork(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) - // FYI scope and version are currently unused but are described by the API - // Leaving this for if/when we have to enable these - // query := struct { - // scope string - // verbose bool - // }{ - // // override any golang type defaults - // } - // decoder := r.Context().Value("decoder").(*schema.Decoder) - // if err := decoder.Decode(&query, r.URL.Query()); err != nil { - // utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) - // return - // } + // scope is only used to see if the user passes any illegal value, verbose is not used but implemented + // for compatibility purposes only. + query := struct { + scope string `schema:"scope"` + verbose bool `schema:"verbose"` + }{ + scope: "local", + } + decoder := r.Context().Value("decoder").(*schema.Decoder) + if err := decoder.Decode(&query, r.URL.Query()); err != nil { + utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + return + } + + if query.scope != "local" { + utils.Error(w, "Invalid scope value. Can only be local.", http.StatusBadRequest, define.ErrInvalidArg) + return + } config, err := runtime.GetConfig() if err != nil { utils.InternalServerError(w, err) @@ -414,7 +419,7 @@ func Prune(w http.ResponseWriter, r *http.Request) { type response struct { NetworksDeleted []string } - var prunedNetworks []string //nolint + prunedNetworks := []string{} for _, pr := range pruneReports { if pr.Error != nil { logrus.Error(pr.Error) diff --git a/pkg/api/handlers/compat/swagger.go b/pkg/api/handlers/compat/swagger.go index a0783e723..b773799ef 100644 --- a/pkg/api/handlers/compat/swagger.go +++ b/pkg/api/handlers/compat/swagger.go @@ -77,10 +77,3 @@ type swagCompatNetworkDisconnectRequest struct { // in:body Body struct{ types.NetworkDisconnect } } - -// Network prune -// swagger:response NetworkPruneResponse -type swagCompatNetworkPruneResponse struct { - // in:body - Body []string -} diff --git a/pkg/api/handlers/libpod/images_pull.go b/pkg/api/handlers/libpod/images_pull.go index fe56aa31d..e88b53a4b 100644 --- a/pkg/api/handlers/libpod/images_pull.go +++ b/pkg/api/handlers/libpod/images_pull.go @@ -85,7 +85,7 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) { var pulledImages []*libimage.Image var pullError error - runCtx, cancel := context.WithCancel(context.Background()) + runCtx, cancel := context.WithCancel(r.Context()) go func() { defer cancel() pulledImages, pullError = runtime.LibimageRuntime().Pull(runCtx, query.Reference, config.PullPolicyAlways, pullOptions) diff --git a/pkg/api/handlers/libpod/networks.go b/pkg/api/handlers/libpod/networks.go index 5417f778e..e4f450e12 100644 --- a/pkg/api/handlers/libpod/networks.go +++ b/pkg/api/handlers/libpod/networks.go @@ -190,5 +190,8 @@ func Prune(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err) return } + if pruneReports == nil { + pruneReports = []*entities.NetworkPruneReport{} + } utils.WriteResponse(w, http.StatusOK, pruneReports) } diff --git a/pkg/api/handlers/libpod/swagger.go b/pkg/api/handlers/libpod/swagger.go index 19eced986..2ac5009fc 100644 --- a/pkg/api/handlers/libpod/swagger.go +++ b/pkg/api/handlers/libpod/swagger.go @@ -119,6 +119,13 @@ type swagNetworkCreateReport struct { Body entities.NetworkCreateReport } +// Network prune +// swagger:response NetworkPruneResponse +type swagNetworkPruneResponse struct { + // in:body + Body []entities.NetworkPruneReport +} + func ServeSwagger(w http.ResponseWriter, r *http.Request) { path := DefaultPodmanSwaggerSpec if p, found := os.LookupEnv("PODMAN_SWAGGER_SPEC"); found { diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 9634bd83b..b28818768 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -28,15 +28,28 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // - in: query // name: fromImage // type: string - // description: needs description + // description: Name of the image to pull. The name may include a tag or digest. This parameter may only be used when pulling an image. The pull is cancelled if the HTTP connection is closed. // - in: query // name: fromSrc // type: string - // description: needs description + // description: 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 + // - in: query + // name: repo + // type: string + // description: 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. // - in: query // name: tag // type: string - // description: needs description + // description: Tag or digest. If empty when pulling an image, this causes all tags for the given image to be pulled. + // - in: query + // name: message + // type: string + // description: Set commit message for imported image. + // - in: query + // name: platform + // type: string + // description: Platform in the format os[/arch[/variant]] + // default: "" // - in: header // name: X-Registry-Auth // type: string @@ -45,6 +58,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // name: request // schema: // type: string + // format: binary // description: Image content if fromSrc parameter was used // responses: // 200: diff --git a/pkg/api/server/register_networks.go b/pkg/api/server/register_networks.go index 4d9806316..69c6896b8 100644 --- a/pkg/api/server/register_networks.go +++ b/pkg/api/server/register_networks.go @@ -44,6 +44,16 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error { // type: string // required: true // description: the name of the network + // - in: query + // name: verbose + // type: boolean + // required: false + // description: Detailed inspect output for troubleshooting + // - in: query + // name: scope + // type: string + // required: false + // description: Filter the network by scope (swarm, global, or local) // produces: // - application/json // responses: @@ -180,9 +190,12 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error { // 200: // description: OK // schema: - // type: array - // items: - // type: string + // type: object + // properties: + // NetworksDeleted: + // type: array + // items: + // type: string // 500: // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/networks/prune"), s.APIHandler(compat.Prune)).Methods(http.MethodPost) diff --git a/test/apiv2/python/rest_api/test_v2_0_0_image.py b/test/apiv2/python/rest_api/test_v2_0_0_image.py index 243b1d5f5..2cd7bfa96 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_image.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_image.py @@ -86,6 +86,11 @@ class ImageTestCase(APITestCase): self.assertTrue(keys["id"], "Expected to find id stanza") self.assertTrue(keys["images"], "Expected to find images stanza") self.assertTrue(keys["stream"], "Expected to find stream progress stanza's") + def test_create(self): + r = requests.post(self.podman_url + "/v1.40/images/create?fromImage=alpine&platform=linux/amd64/v8", timeout=15) + self.assertEqual(r.status_code, 200, r.text) + r = requests.post(self.podman_url + "/v1.40/images/create?fromSrc=-&repo=fedora&message=testing123", timeout=15) + self.assertEqual(r.status_code, 200, r.text) def test_search_compat(self): url = self.podman_url + "/v1.40/images/search" diff --git a/test/apiv2/python/rest_api/test_v2_0_0_network.py b/test/apiv2/python/rest_api/test_v2_0_0_network.py index 3888123fb..d606b9351 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_network.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_network.py @@ -102,6 +102,33 @@ class NetworkTestCase(APITestCase): "TestNetwork", payload["NetworkSettings"]["Networks"]["TestNetwork"]["NetworkID"], ) + def test_inspect(self): + name = f"Network_{random.getrandbits(160):x}" + create = requests.post(self.podman_url + "/v1.40/networks/create", json={"Name": name}) + self.assertEqual(create.status_code, 201, create.text) + self.assertId(create.content) + + net = create.json() + self.assertIsInstance(net, dict) + self.assertNotEqual(net["Id"], name) + ident = net["Id"] + + ls = requests.get(self.podman_url + "/v1.40/networks") + self.assertEqual(ls.status_code, 200, ls.text) + + networks = ls.json() + self.assertIsInstance(networks, list) + + found = False + for net in networks: + if net["Name"] == name: + found = True + break + self.assertTrue(found, f"Network '{name}' not found") + + inspect = requests.get(self.podman_url + f"/v1.40/networks/{ident}?verbose=false&scope=local") + self.assertEqual(inspect.status_code, 200, inspect.text) + def test_crud(self): name = f"Network_{random.getrandbits(160):x}" diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go index 4d9cbb48b..b576fa072 100644 --- a/test/e2e/logs_test.go +++ b/test/e2e/logs_test.go @@ -173,9 +173,9 @@ var _ = Describe("Podman logs", func() { }) It("streaming output: "+log, func() { - containerName := "logs-f-rm" + containerName := "logs-f" - logc := podmanTest.Podman([]string{"run", "--log-driver", log, "--rm", "--name", containerName, "-dt", ALPINE, "sh", "-c", "echo podman; sleep 1; echo podman"}) + logc := podmanTest.Podman([]string{"run", "--log-driver", log, "--name", containerName, "-dt", ALPINE, "sh", "-c", "echo podman-1; sleep 1; echo podman-2"}) logc.WaitWithDefaultTimeout() Expect(logc).To(Exit(0)) @@ -183,10 +183,8 @@ var _ = Describe("Podman logs", func() { results.WaitWithDefaultTimeout() Expect(results).To(Exit(0)) - // TODO: we should actually check for two podman lines, - // but as of 2020-06-17 there's a race condition in which - // 'logs -f' may not catch all output from a container - Expect(results.OutputToString()).To(ContainSubstring("podman")) + Expect(results.OutputToString()).To(ContainSubstring("podman-1")) + Expect(results.OutputToString()).To(ContainSubstring("podman-2")) // Container should now be terminatING or terminatED, but we // have no guarantee of which: 'logs -f' does not necessarily @@ -199,6 +197,10 @@ var _ = Describe("Podman logs", func() { } else { Expect(inspect.ErrorToString()).To(ContainSubstring("no such container")) } + + results = podmanTest.Podman([]string{"rm", "-f", containerName}) + results.WaitWithDefaultTimeout() + Expect(results).To(Exit(0)) }) It("follow output stopped container: "+log, func() { diff --git a/vendor/github.com/containers/buildah/CHANGELOG.md b/vendor/github.com/containers/buildah/CHANGELOG.md index 7a0af9298..ab704400f 100644 --- a/vendor/github.com/containers/buildah/CHANGELOG.md +++ b/vendor/github.com/containers/buildah/CHANGELOG.md @@ -1,6 +1,9 @@ ![buildah logo](https://cdn.rawgit.com/containers/buildah/master/logos/buildah-logo_large.png) # Changelog +## v1.21.1 (2021-06-02) + Fix handling of auth.json file while in a user namespace + ## v1.21.0 (2021-05-19) Don't blow up if cpp detects errors Vendor in containers/common v0.38.4 diff --git a/vendor/github.com/containers/buildah/changelog.txt b/vendor/github.com/containers/buildah/changelog.txt index 3bde05a3e..ee0e9b61f 100644 --- a/vendor/github.com/containers/buildah/changelog.txt +++ b/vendor/github.com/containers/buildah/changelog.txt @@ -1,3 +1,6 @@ +- Changelog for v1.21.1 (2021-06-03) + * Fix handling of auth.json file while in a user namespace + - Changelog for v1.21.0 (2021-05-19) * Don't blow up if cpp detects errors * Vendor in containers/common v0.38.4 diff --git a/vendor/github.com/containers/buildah/define/types.go b/vendor/github.com/containers/buildah/define/types.go index f2327e8df..ac2071b37 100644 --- a/vendor/github.com/containers/buildah/define/types.go +++ b/vendor/github.com/containers/buildah/define/types.go @@ -28,7 +28,7 @@ const ( Package = "buildah" // Version for the Package. Bump version in contrib/rpm/buildah.spec // too. - Version = "1.21.0" + Version = "1.21.1" // DefaultRuntime if containers.conf fails. DefaultRuntime = "runc" diff --git a/vendor/modules.txt b/vendor/modules.txt index 786096f45..a00f1becc 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -77,7 +77,7 @@ github.com/containernetworking/plugins/pkg/utils/hwaddr github.com/containernetworking/plugins/pkg/utils/sysctl github.com/containernetworking/plugins/plugins/ipam/host-local/backend github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator -# github.com/containers/buildah v1.21.0 +# github.com/containers/buildah v1.21.1 github.com/containers/buildah github.com/containers/buildah/bind github.com/containers/buildah/chroot |