diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/api/handlers/compat/containers.go | 23 | ||||
-rw-r--r-- | pkg/api/handlers/compat/containers_logs.go | 6 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images.go | 4 | ||||
-rw-r--r-- | pkg/api/handlers/compat/networks.go | 82 | ||||
-rw-r--r-- | pkg/api/handlers/compat/swagger.go | 14 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/images.go | 3 | ||||
-rw-r--r-- | pkg/api/handlers/types.go | 11 | ||||
-rw-r--r-- | pkg/api/server/register_networks.go | 57 | ||||
-rw-r--r-- | pkg/domain/entities/images.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images.go | 4 | ||||
-rw-r--r-- | pkg/spec/security.go | 2 | ||||
-rw-r--r-- | pkg/spec/storage.go | 6 | ||||
-rw-r--r-- | pkg/specgen/generate/container_create.go | 17 | ||||
-rw-r--r-- | pkg/util/utils.go | 4 | ||||
-rw-r--r-- | pkg/varlinkapi/images.go | 2 |
15 files changed, 203 insertions, 34 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index cae8f88fd..00be8e845 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -410,25 +410,14 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, return nil, err } - networkSettingsDefault := types.DefaultNetworkSettings{ - EndpointID: "", - Gateway: "", - GlobalIPv6Address: "", - GlobalIPv6PrefixLen: 0, - IPAddress: "", - IPPrefixLen: 0, - IPv6Gateway: "", - MacAddress: l.Config().StaticMAC.String(), - } - - networkSettingsBase := types.NetworkSettingsBase{ - Ports: ports, + n, err := json.Marshal(inspect.NetworkSettings) + if err != nil { + return nil, err } - networkSettings := types.NetworkSettings{ - NetworkSettingsBase: networkSettingsBase, - DefaultNetworkSettings: networkSettingsDefault, - Networks: nil, + networkSettings := types.NetworkSettings{} + if err := json.Unmarshal(n, &networkSettings); err != nil { + return nil, err } c := types.ContainerJSON{ diff --git a/pkg/api/handlers/compat/containers_logs.go b/pkg/api/handlers/compat/containers_logs.go index faab66fe7..38a6329b9 100644 --- a/pkg/api/handlers/compat/containers_logs.go +++ b/pkg/api/handlers/compat/containers_logs.go @@ -148,7 +148,13 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) { frame.WriteString(line.Time.Format(time.RFC3339)) frame.WriteString(" ") } + frame.WriteString(line.Msg) + // Log lines in the compat layer require adding EOL + // https://github.com/containers/podman/issues/8058 + if !utils.IsLibpodRequest(r) { + frame.WriteString("\n") + } if writeHeader { binary.BigEndian.PutUint32(header[4:], uint32(frame.Len())) diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go index 3431823bd..d177b2335 100644 --- a/pkg/api/handlers/compat/images.go +++ b/pkg/api/handlers/compat/images.go @@ -60,7 +60,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile")) return } - if err := newImage.Save(r.Context(), name, "docker-archive", tmpfile.Name(), []string{}, false, false); err != nil { + if err := newImage.Save(r.Context(), name, "docker-archive", tmpfile.Name(), []string{}, false, false, true); err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to save image")) return } @@ -429,7 +429,7 @@ func ExportImages(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile")) return } - if err := runtime.ImageRuntime().SaveImages(r.Context(), images, "docker-archive", tmpfile.Name(), false); err != nil { + if err := runtime.ImageRuntime().SaveImages(r.Context(), images, "docker-archive", tmpfile.Name(), false, true); err != nil { utils.InternalServerError(w, err) return } diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go index a46784a6c..8011c0a04 100644 --- a/pkg/api/handlers/compat/networks.go +++ b/pkg/api/handlers/compat/networks.go @@ -20,6 +20,7 @@ import ( dockerNetwork "github.com/docker/docker/api/types/network" "github.com/gorilla/schema" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) func InspectNetwork(w http.ResponseWriter, r *http.Request) { @@ -231,6 +232,9 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) { if len(networkCreate.Name) > 0 { name = networkCreate.Name } + if len(networkCreate.Driver) < 1 { + networkCreate.Driver = network.DefaultNetworkDriver + } // At present I think we should just support the bridge driver // and allow demand to make us consider more if networkCreate.Driver != network.DefaultNetworkDriver { @@ -312,3 +316,81 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) { } utils.WriteResponse(w, http.StatusNoContent, "") } + +// Connect adds a container to a network +// TODO: For now this func is a no-op that checks the container name, network name, and +// responds with a 200. This allows the call to remain intact. We need to decide how +// we make this work with CNI networking and setup/teardown. +func Connect(w http.ResponseWriter, r *http.Request) { + runtime := r.Context().Value("runtime").(*libpod.Runtime) + + var netConnect types.NetworkConnect + if err := json.NewDecoder(r.Body).Decode(&netConnect); err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + return + } + config, err := runtime.GetConfig() + if err != nil { + utils.InternalServerError(w, err) + return + } + name := utils.GetName(r) + exists, err := network.Exists(config, name) + if err != nil { + utils.InternalServerError(w, err) + return + } + if !exists { + utils.Error(w, "network not found", http.StatusNotFound, define.ErrNoSuchNetwork) + return + } + if _, err = runtime.LookupContainer(netConnect.Container); err != nil { + if errors.Cause(err) == define.ErrNoSuchCtr { + utils.ContainerNotFound(w, netConnect.Container, err) + return + } + utils.Error(w, "unable to lookup container", http.StatusInternalServerError, err) + return + } + logrus.Warnf("network connect endpoint is not fully implemented - tried to connect container %s to network %s", netConnect.Container, name) + utils.WriteResponse(w, http.StatusOK, "OK") +} + +// Disconnect removes a container from a network +// TODO: For now this func is a no-op that checks the container name, network name, and +// responds with a 200. This allows the call to remain intact. We need to decide how +// we make this work with CNI networking and setup/teardown. +func Disconnect(w http.ResponseWriter, r *http.Request) { + runtime := r.Context().Value("runtime").(*libpod.Runtime) + + var netDisconnect types.NetworkDisconnect + if err := json.NewDecoder(r.Body).Decode(&netDisconnect); err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + return + } + config, err := runtime.GetConfig() + if err != nil { + utils.InternalServerError(w, err) + return + } + name := utils.GetName(r) + exists, err := network.Exists(config, name) + if err != nil { + utils.InternalServerError(w, err) + return + } + if !exists { + utils.Error(w, "network not found", http.StatusNotFound, define.ErrNoSuchNetwork) + return + } + if _, err = runtime.LookupContainer(netDisconnect.Container); err != nil { + if errors.Cause(err) == define.ErrNoSuchCtr { + utils.ContainerNotFound(w, netDisconnect.Container, err) + return + } + utils.Error(w, "unable to lookup container", http.StatusInternalServerError, err) + return + } + logrus.Warnf("network disconnect endpoint is not fully implemented - tried to connect container %s to network %s", netDisconnect.Container, name) + utils.WriteResponse(w, http.StatusOK, "OK") +} diff --git a/pkg/api/handlers/compat/swagger.go b/pkg/api/handlers/compat/swagger.go index 371d02388..0a514822b 100644 --- a/pkg/api/handlers/compat/swagger.go +++ b/pkg/api/handlers/compat/swagger.go @@ -63,3 +63,17 @@ type swagCompatNetworkCreateResponse struct { // in:body Body struct{ types.NetworkCreate } } + +// Network disconnect +// swagger:model NetworkConnectRequest +type swagCompatNetworkConnectRequest struct { + // in:body + Body struct{ types.NetworkConnect } +} + +// Network disconnect +// swagger:model NetworkDisconnectRequest +type swagCompatNetworkDisconnectRequest struct { + // in:body + Body struct{ types.NetworkDisconnect } +} diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index 3fb5d23c8..598a46abe 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -206,7 +206,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { utils.Error(w, "unknown format", http.StatusInternalServerError, errors.Errorf("unknown format %q", query.Format)) return } - if err := newImage.Save(r.Context(), name, query.Format, output, []string{}, false, query.Compress); err != nil { + if err := newImage.Save(r.Context(), name, query.Format, output, []string{}, false, query.Compress, true); err != nil { utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err) return } @@ -284,6 +284,7 @@ func ExportImages(w http.ResponseWriter, r *http.Request) { Format: query.Format, MultiImageArchive: true, Output: output, + RemoveSignatures: true, } imageEngine := abi.ImageEngine{Libpod: runtime} diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index 70466f01b..6bb5f5101 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -271,6 +271,15 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI if err != nil { return nil, err } + + rootfs := docker.RootFS{} + if info.RootFS != nil { + rootfs.Type = info.RootFS.Type + rootfs.Layers = make([]string, 0, len(info.RootFS.Layers)) + for _, layer := range info.RootFS.Layers { + rootfs.Layers = append(rootfs.Layers, string(layer)) + } + } dockerImageInspect := docker.ImageInspect{ Architecture: l.Architecture, Author: l.Author, @@ -286,7 +295,7 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI Parent: l.Parent, RepoDigests: info.RepoDigests, RepoTags: info.RepoTags, - RootFS: docker.RootFS{}, + RootFS: rootfs, Size: info.Size, Variant: "", VirtualSize: info.VirtualSize, diff --git a/pkg/api/server/register_networks.go b/pkg/api/server/register_networks.go index 61916eedf..6222006e5 100644 --- a/pkg/api/server/register_networks.go +++ b/pkg/api/server/register_networks.go @@ -98,6 +98,63 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error { // $ref: "#/responses/InternalError" r.HandleFunc(VersionedPath("/networks/create"), s.APIHandler(compat.CreateNetwork)).Methods(http.MethodPost) r.HandleFunc("/networks/create", s.APIHandler(compat.CreateNetwork)).Methods(http.MethodPost) + // swagger:operation POST /networks/{name}/connect compat compatConnectNetwork + // --- + // tags: + // - networks (compat) + // summary: Connect container to network + // description: Connect a container to a network. This endpoint is current a no-op + // produces: + // - application/json + // parameters: + // - in: path + // name: name + // type: string + // required: true + // description: the name of the network + // - in: body + // name: create + // description: attributes for connecting a container to a network + // schema: + // $ref: "#/definitions/NetworkConnectRequest" + // responses: + // 200: + // description: OK + // 400: + // $ref: "#/responses/BadParamError" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/networks/{name}/connect"), s.APIHandler(compat.Connect)).Methods(http.MethodPost) + r.HandleFunc("/networks/{name}/connect", s.APIHandler(compat.Connect)).Methods(http.MethodPost) + // swagger:operation POST /networks/{name}/disconnect compat compatDisconnectNetwork + // --- + // tags: + // - networks (compat) + // summary: Disconnect container from network + // description: Disconnect a container from a network. This endpoint is current a no-op + // produces: + // - application/json + // parameters: + // - in: path + // name: name + // type: string + // required: true + // description: the name of the network + // - in: body + // name: create + // description: attributes for disconnecting a container from a network + // schema: + // $ref: "#/definitions/NetworkDisconnectRequest" + // responses: + // 200: + // description: OK + // 400: + // $ref: "#/responses/BadParamError" + // 500: + // $ref: "#/responses/InternalError" + r.HandleFunc(VersionedPath("/networks/{name}/disconnect"), s.APIHandler(compat.Disconnect)).Methods(http.MethodPost) + r.HandleFunc("/networks/{name}/disconnect", s.APIHandler(compat.Disconnect)).Methods(http.MethodPost) + // swagger:operation DELETE /libpod/networks/{name} libpod libpodRemoveNetwork // --- // tags: diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index 982fa0cc0..101542a98 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -300,6 +300,8 @@ type ImageSaveOptions struct { MultiImageArchive bool // Output - write image to the specified path. Output string + // Do not save the signature from the source image + RemoveSignatures bool // Quiet - suppress output when copying images Quiet bool } diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index f9d733c63..25335cf11 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -482,13 +482,13 @@ func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOpti func (ir *ImageEngine) Save(ctx context.Context, nameOrID string, tags []string, options entities.ImageSaveOptions) error { if options.MultiImageArchive { nameOrIDs := append([]string{nameOrID}, tags...) - return ir.Libpod.ImageRuntime().SaveImages(ctx, nameOrIDs, options.Format, options.Output, options.Quiet) + return ir.Libpod.ImageRuntime().SaveImages(ctx, nameOrIDs, options.Format, options.Output, options.Quiet, true) } newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrID) if err != nil { return err } - return newImage.Save(ctx, nameOrID, options.Format, options.Output, tags, options.Quiet, options.Compress) + return newImage.Save(ctx, nameOrID, options.Format, options.Output, tags, options.Quiet, options.Compress, true) } func (ir *ImageEngine) Diff(_ context.Context, nameOrID string, _ entities.DiffOptions) (*entities.DiffReport, error) { diff --git a/pkg/spec/security.go b/pkg/spec/security.go index e152e3495..5f7db7edb 100644 --- a/pkg/spec/security.go +++ b/pkg/spec/security.go @@ -178,7 +178,7 @@ func (c *SecurityConfig) ConfigureGenerator(g *generate.Generator, user *UserCon for _, opt := range c.SecurityOpts { // Split on both : and = - splitOpt := strings.Split(opt, "=") + splitOpt := strings.SplitN(opt, "=", 2) if len(splitOpt) == 1 { splitOpt = strings.Split(opt, ":") } diff --git a/pkg/spec/storage.go b/pkg/spec/storage.go index 5e2f04e50..ebf5ec196 100644 --- a/pkg/spec/storage.go +++ b/pkg/spec/storage.go @@ -394,7 +394,7 @@ func getBindMount(args []string) (spec.Mount, error) { var setSource, setDest, setRORW, setSuid, setDev, setExec, setRelabel bool for _, val := range args { - kv := strings.Split(val, "=") + kv := strings.SplitN(val, "=", 2) switch kv[0] { case "bind-nonrecursive": newMount.Options = append(newMount.Options, "bind") @@ -517,7 +517,7 @@ func getTmpfsMount(args []string) (spec.Mount, error) { var setDest, setRORW, setSuid, setDev, setExec, setTmpcopyup bool for _, val := range args { - kv := strings.Split(val, "=") + kv := strings.SplitN(val, "=", 2) switch kv[0] { case "tmpcopyup", "notmpcopyup": if setTmpcopyup { @@ -591,7 +591,7 @@ func getNamedVolume(args []string) (*libpod.ContainerNamedVolume, error) { var setSource, setDest, setRORW, setSuid, setDev, setExec bool for _, val := range args { - kv := strings.Split(val, "=") + kv := strings.SplitN(val, "=", 2) switch kv[0] { case "ro", "rw": if setRORW { diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index 105e36bc6..f051537de 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -4,6 +4,7 @@ import ( "context" "os" "path/filepath" + "strings" "github.com/containers/common/pkg/config" "github.com/containers/podman/v2/libpod" @@ -91,11 +92,19 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener if err != nil { return nil, err } - imgName := s.Image - names := newImage.Names() - if len(names) > 0 { - imgName = names[0] + // If the input name changed, we could properly resolve the + // image. Otherwise, it must have been an ID where we're + // defaulting to the first name or an empty one if no names are + // present. + imgName := newImage.InputName + if s.Image == newImage.InputName && strings.HasPrefix(newImage.ID(), s.Image) { + imgName = "" + names := newImage.Names() + if len(names) > 0 { + imgName = names[0] + } } + options = append(options, libpod.WithRootFSFromImage(newImage.ID(), imgName, s.RawImageName)) } if err := s.Validate(); err != nil { diff --git a/pkg/util/utils.go b/pkg/util/utils.go index c3a70e2fb..91aba9fa7 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -474,8 +474,8 @@ func getTomlStorage(storeOptions *storage.StoreOptions) *tomlConfig { config.Storage.RunRoot = storeOptions.RunRoot config.Storage.GraphRoot = storeOptions.GraphRoot for _, i := range storeOptions.GraphDriverOptions { - s := strings.Split(i, "=") - if s[0] == "overlay.mount_program" { + s := strings.SplitN(i, "=", 2) + if s[0] == "overlay.mount_program" && len(s) == 2 { config.Storage.Options.MountProgram = s[1] } } diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go index ef310d590..af6c43fec 100644 --- a/pkg/varlinkapi/images.go +++ b/pkg/varlinkapi/images.go @@ -843,7 +843,7 @@ func (i *VarlinkAPI) ImageSave(call iopodman.VarlinkCall, options iopodman.Image saveOutput := bytes.NewBuffer([]byte{}) c := make(chan error) go func() { - err := newImage.Save(getContext(), options.Name, options.Format, output, options.MoreTags, options.Quiet, options.Compress) + err := newImage.Save(getContext(), options.Name, options.Format, output, options.MoreTags, options.Quiet, options.Compress, true) c <- err close(c) }() |