diff options
Diffstat (limited to 'pkg')
23 files changed, 219 insertions, 45 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index ae063dc9f..0b82c48f6 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -467,6 +467,7 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, if err := json.Unmarshal(h, &hc); err != nil { return nil, err } + sort.Strings(hc.Binds) // k8s-file == json-file if hc.LogConfig.Type == define.KubernetesLogging { diff --git a/pkg/api/handlers/libpod/kube.go b/pkg/api/handlers/libpod/kube.go index 6cad58795..5c891b707 100644 --- a/pkg/api/handlers/libpod/kube.go +++ b/pkg/api/handlers/libpod/kube.go @@ -121,3 +121,7 @@ func KubePlayDown(w http.ResponseWriter, r *http.Request) { } utils.WriteResponse(w, http.StatusOK, report) } + +func KubeGenerate(w http.ResponseWriter, r *http.Request) { + GenerateKube(w, r) +} diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go index b0c93f3b9..fa83bbfe1 100644 --- a/pkg/api/handlers/libpod/manifests.go +++ b/pkg/api/handlers/libpod/manifests.go @@ -36,6 +36,7 @@ func ManifestCreate(w http.ResponseWriter, r *http.Request) { Name string `schema:"name"` Images []string `schema:"images"` All bool `schema:"all"` + Amend bool `schema:"amend"` }{ // Add defaults here once needed. } @@ -70,7 +71,7 @@ func ManifestCreate(w http.ResponseWriter, r *http.Request) { imageEngine := abi.ImageEngine{Libpod: runtime} - createOptions := entities.ManifestCreateOptions{All: query.All} + createOptions := entities.ManifestCreateOptions{All: query.All, Amend: query.Amend} manID, err := imageEngine.ManifestCreate(r.Context(), query.Name, query.Images, createOptions) if err != nil { utils.InternalServerError(w, err) diff --git a/pkg/api/server/register_play.go b/pkg/api/server/register_kube.go index 76e150504..0c3cd1d04 100644 --- a/pkg/api/server/register_play.go +++ b/pkg/api/server/register_kube.go @@ -7,7 +7,7 @@ import ( "github.com/gorilla/mux" ) -func (s *APIServer) registerPlayHandlers(r *mux.Router) error { +func (s *APIServer) registerKubeHandlers(r *mux.Router) error { // swagger:operation POST /libpod/play/kube libpod PlayKubeLibpod // --- // tags: @@ -78,5 +78,38 @@ func (s *APIServer) registerPlayHandlers(r *mux.Router) error { // $ref: "#/responses/internalError" r.HandleFunc(VersionedPath("/libpod/play/kube"), s.APIHandler(libpod.PlayKubeDown)).Methods(http.MethodDelete) r.HandleFunc(VersionedPath("/libpod/kube/play"), s.APIHandler(libpod.KubePlayDown)).Methods(http.MethodDelete) + // swagger:operation GET /libpod/generate/kube libpod GenerateKubeLibpod + // --- + // tags: + // - containers + // - pods + // summary: Generate a Kubernetes YAML file. + // description: Generate Kubernetes YAML based on a pod or container. + // parameters: + // - in: query + // name: names + // type: array + // items: + // type: string + // required: true + // description: Name or ID of the container or pod. + // - in: query + // name: service + // type: boolean + // default: false + // description: Generate YAML for a Kubernetes service object. + // produces: + // - text/vnd.yaml + // - application/json + // responses: + // 200: + // description: Kubernetes YAML file describing pod + // schema: + // type: string + // format: binary + // 500: + // $ref: "#/responses/internalError" + r.HandleFunc(VersionedPath("/libpod/generate/kube"), s.APIHandler(libpod.GenerateKube)).Methods(http.MethodGet) + r.HandleFunc(VersionedPath("/libpod/kube/generate"), s.APIHandler(libpod.KubeGenerate)).Methods(http.MethodGet) return nil } diff --git a/pkg/api/server/register_manifest.go b/pkg/api/server/register_manifest.go index c22479cf9..7a55eaefe 100644 --- a/pkg/api/server/register_manifest.go +++ b/pkg/api/server/register_manifest.go @@ -117,6 +117,10 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error { // name: all // type: boolean // description: add all contents if given list + // - in: query + // name: amend + // type: boolean + // description: modify an existing list if one with the desired name already exists // - in: body // name: options // description: options for new manifest diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go index 5482a8ec2..39423dabe 100644 --- a/pkg/api/server/server.go +++ b/pkg/api/server/server.go @@ -130,7 +130,7 @@ func newServer(runtime *libpod.Runtime, listener net.Listener, opts entities.Ser server.registerMonitorHandlers, server.registerNetworkHandlers, server.registerPingHandlers, - server.registerPlayHandlers, + server.registerKubeHandlers, server.registerPluginsHandlers, server.registerPodsHandlers, server.registerSecretHandlers, diff --git a/pkg/bindings/kube/kube.go b/pkg/bindings/kube/kube.go index db40c5134..e727439cf 100644 --- a/pkg/bindings/kube/kube.go +++ b/pkg/bindings/kube/kube.go @@ -10,6 +10,7 @@ import ( "github.com/containers/image/v5/types" "github.com/containers/podman/v4/pkg/auth" "github.com/containers/podman/v4/pkg/bindings" + "github.com/containers/podman/v4/pkg/bindings/generate" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/sirupsen/logrus" ) @@ -94,3 +95,8 @@ func DownWithBody(ctx context.Context, body io.Reader) (*entities.KubePlayReport } return &report, nil } + +// Kube generate Kubernetes YAML (v1 specification) +func Generate(ctx context.Context, nameOrIDs []string, options generate.KubeOptions) (*entities.GenerateKubeReport, error) { + return generate.Kube(ctx, nameOrIDs, &options) +} diff --git a/pkg/bindings/manifests/types.go b/pkg/bindings/manifests/types.go index e23ef798d..5f2557fe1 100644 --- a/pkg/bindings/manifests/types.go +++ b/pkg/bindings/manifests/types.go @@ -8,7 +8,8 @@ type InspectOptions struct { //go:generate go run ../generator/generator.go CreateOptions // CreateOptions are optional options for creating manifests type CreateOptions struct { - All *bool + All *bool + Amend *bool } //go:generate go run ../generator/generator.go ExistsOptions diff --git a/pkg/bindings/manifests/types_create_options.go b/pkg/bindings/manifests/types_create_options.go index 960332a82..09942c00a 100644 --- a/pkg/bindings/manifests/types_create_options.go +++ b/pkg/bindings/manifests/types_create_options.go @@ -31,3 +31,18 @@ func (o *CreateOptions) GetAll() bool { } return *o.All } + +// WithAmend set field Amend to given value +func (o *CreateOptions) WithAmend(value bool) *CreateOptions { + o.Amend = &value + return o +} + +// GetAmend returns value of field Amend +func (o *CreateOptions) GetAmend() bool { + if o.Amend == nil { + var z bool + return z + } + return *o.Amend +} diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go index 3ba507750..91ccdc2b2 100644 --- a/pkg/domain/entities/containers.go +++ b/pkg/domain/entities/containers.go @@ -119,6 +119,7 @@ type KillReport struct { } type RestartOptions struct { + Filters map[string][]string All bool Latest bool Running bool @@ -126,8 +127,9 @@ type RestartOptions struct { } type RestartReport struct { - Err error - Id string //nolint:revive,stylecheck + Err error + Id string //nolint:revive,stylecheck + RawInput string } type RmOptions struct { diff --git a/pkg/domain/entities/generate.go b/pkg/domain/entities/generate.go index cc5fbb6fb..f18e79b47 100644 --- a/pkg/domain/entities/generate.go +++ b/pkg/domain/entities/generate.go @@ -46,6 +46,8 @@ type GenerateKubeOptions struct { Service bool } +type KubeGenerateOptions = GenerateKubeOptions + // GenerateKubeReport // // FIXME: Podman4.0 should change io.Reader to io.ReaderCloser diff --git a/pkg/domain/entities/manifest.go b/pkg/domain/entities/manifest.go index 126b76c62..f17079271 100644 --- a/pkg/domain/entities/manifest.go +++ b/pkg/domain/entities/manifest.go @@ -4,7 +4,12 @@ import "github.com/containers/image/v5/types" // ManifestCreateOptions provides model for creating manifest type ManifestCreateOptions struct { + // True when adding lists to include all images All bool `schema:"all"` + // Amend an extant list if there's already one with the desired name + Amend bool `schema:"amend"` + // Should TLS registry certificate be verified? + SkipTLSVerify types.OptionalBool `json:"-" schema:"-"` } // ManifestAddOptions provides model for adding digests to manifest list diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 5b5bc665e..08d845d70 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -309,31 +309,42 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []string, options entities.RestartOptions) ([]*entities.RestartReport, error) { var ( - ctrs []*libpod.Container - err error + ctrs []*libpod.Container + err error + rawInputs = []string{} ) if options.Running { ctrs, err = ic.Libpod.GetRunningContainers() + for _, candidate := range ctrs { + rawInputs = append(rawInputs, candidate.ID()) + } + if err != nil { return nil, err } } else { - ctrs, err = getContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod) + ctrs, rawInputs, err = getContainersAndInputByContext(options.All, options.Latest, namesOrIds, options.Filters, ic.Libpod) if err != nil { return nil, err } } - + idToRawInput := map[string]string{} + if len(rawInputs) == len(ctrs) { + for i := range ctrs { + idToRawInput[ctrs[i].ID()] = rawInputs[i] + } + } reports := make([]*entities.RestartReport, 0, len(ctrs)) - for _, con := range ctrs { - timeout := con.StopTimeout() + for _, c := range ctrs { + timeout := c.StopTimeout() if options.Timeout != nil { timeout = *options.Timeout } reports = append(reports, &entities.RestartReport{ - Id: con.ID(), - Err: con.RestartWithTimeout(ctx, timeout), + Id: c.ID(), + Err: c.RestartWithTimeout(ctx, timeout), + RawInput: idToRawInput[c.ID()], }) } return reports, nil diff --git a/pkg/domain/infra/abi/manifest.go b/pkg/domain/infra/abi/manifest.go index e0c11267e..7e8c86526 100644 --- a/pkg/domain/infra/abi/manifest.go +++ b/pkg/domain/infra/abi/manifest.go @@ -32,7 +32,15 @@ func (ir *ImageEngine) ManifestCreate(ctx context.Context, name string, images [ manifestList, err := ir.Libpod.LibimageRuntime().CreateManifestList(name) if err != nil { - return "", err + if errors.Is(err, storage.ErrDuplicateName) && opts.Amend { + amendList, amendErr := ir.Libpod.LibimageRuntime().LookupManifestList(name) + if amendErr != nil { + return "", err + } + manifestList = amendList + } else { + return "", err + } } addOptions := &libimage.ManifestListAddOptions{All: opts.All} diff --git a/pkg/domain/infra/abi/terminal/terminal_unsupported.go b/pkg/domain/infra/abi/terminal/terminal_unsupported.go new file mode 100644 index 000000000..8fe325736 --- /dev/null +++ b/pkg/domain/infra/abi/terminal/terminal_unsupported.go @@ -0,0 +1,25 @@ +//go:build !linux +// +build !linux + +package terminal + +import ( + "context" + "errors" + "os" + + "github.com/containers/podman/v4/libpod" + "github.com/containers/podman/v4/libpod/define" +) + +// ExecAttachCtr execs and attaches to a container +func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpod.ExecConfig, streams *define.AttachStreams) (int, error) { + return -1, errors.New("not implemented ExecAttachCtr") +} + +// StartAttachCtr starts and (if required) attaches to a container +// if you change the signature of this function from os.File to io.Writer, it will trigger a downstream +// error. we may need to just lint disable this one. +func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool) error { //nolint: interfacer + return errors.New("not implemented StartAttachCtr") +} diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index d49f029d5..046509140 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -183,17 +183,22 @@ func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []st if to := opts.Timeout; to != nil { options.WithTimeout(int(*to)) } - ctrs, err := getContainersByContext(ic.ClientCtx, opts.All, false, namesOrIds) + ctrs, rawInputs, err := getContainersAndInputByContext(ic.ClientCtx, opts.All, false, namesOrIds, opts.Filters) if err != nil { return nil, err } + idToRawInput := map[string]string{} + for i := range ctrs { + idToRawInput[ctrs[i].ID] = rawInputs[i] + } for _, c := range ctrs { if opts.Running && c.State != define.ContainerStateRunning.String() { continue } reports = append(reports, &entities.RestartReport{ - Id: c.ID, - Err: containers.Restart(ic.ClientCtx, c.ID, options), + Id: c.ID, + Err: containers.Restart(ic.ClientCtx, c.ID, options), + RawInput: idToRawInput[c.ID], }) } return reports, nil diff --git a/pkg/domain/infra/tunnel/manifest.go b/pkg/domain/infra/tunnel/manifest.go index 2a514861d..2e6134051 100644 --- a/pkg/domain/infra/tunnel/manifest.go +++ b/pkg/domain/infra/tunnel/manifest.go @@ -15,7 +15,7 @@ import ( // ManifestCreate implements manifest create via ImageEngine func (ir *ImageEngine) ManifestCreate(ctx context.Context, name string, images []string, opts entities.ManifestCreateOptions) (string, error) { - options := new(manifests.CreateOptions).WithAll(opts.All) + options := new(manifests.CreateOptions).WithAll(opts.All).WithAmend(opts.Amend) imageID, err := manifests.Create(ir.ClientCtx, name, images, options) if err != nil { return imageID, fmt.Errorf("error creating manifest: %w", err) diff --git a/pkg/machine/e2e/basic_test.go b/pkg/machine/e2e/basic_test.go index da0310485..fa1728770 100644 --- a/pkg/machine/e2e/basic_test.go +++ b/pkg/machine/e2e/basic_test.go @@ -1,6 +1,8 @@ package e2e_test import ( + "os" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gexec" @@ -20,6 +22,12 @@ var _ = Describe("run basic podman commands", func() { }) It("Basic ops", func() { + // golangci-lint has trouble with actually skipping tests marked Skip + // so skip it on cirrus envs and where CIRRUS_CI isn't set. + if os.Getenv("CIRRUS_CI") != "false" { + Skip("FIXME: #15347 - ssh know hosts broken - fails on PR runs and on x86_64") + } + name := randomString() i := new(initMachine) session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withNow()).run() diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index b0012b32b..8c4316dbb 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -251,20 +251,22 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo return false, 0, nil } - if mounts, err := pmount.GetMounts(); err == nil { - for _, m := range mounts { - if m.Mountpoint == "/" { - isShared := false - for _, o := range strings.Split(m.Optional, ",") { - if strings.HasPrefix(o, "shared:") { - isShared = true - break + if _, inContainer := os.LookupEnv("container"); !inContainer { + if mounts, err := pmount.GetMounts(); err == nil { + for _, m := range mounts { + if m.Mountpoint == "/" { + isShared := false + for _, o := range strings.Split(m.Optional, ",") { + if strings.HasPrefix(o, "shared:") { + isShared = true + break + } } + if !isShared { + logrus.Warningf("%q is not a shared mount, this could cause issues or missing mounts with rootless containers", m.Mountpoint) + } + break } - if !isShared { - logrus.Warningf("%q is not a shared mount, this could cause issues or missing mounts with rootless containers", m.Mountpoint) - } - break } } } diff --git a/pkg/specgen/generate/config_unsupported.go b/pkg/specgen/generate/config_unsupported.go new file mode 100644 index 000000000..a97ae0709 --- /dev/null +++ b/pkg/specgen/generate/config_unsupported.go @@ -0,0 +1,29 @@ +//go:build !linux +// +build !linux + +package generate + +import ( + "errors" + + "github.com/containers/common/libimage" + "github.com/containers/podman/v4/pkg/specgen" + spec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/opencontainers/runtime-tools/generate" +) + +// DevicesFromPath computes a list of devices +func DevicesFromPath(g *generate.Generator, devicePath string) error { + return errors.New("unsupported DevicesFromPath") +} + +func BlockAccessToKernelFilesystems(privileged, pidModeIsHost bool, mask, unmask []string, g *generate.Generator) { +} + +func supportAmbientCapabilities() bool { + return false +} + +func getSeccompConfig(s *specgen.SpecGenerator, configSpec *spec.Spec, img *libimage.Image) (*spec.LinuxSeccomp, error) { + return nil, errors.New("not implemented getSeccompConfig") +} diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go index f59fe1011..a531494c9 100644 --- a/pkg/specgen/generate/oci.go +++ b/pkg/specgen/generate/oci.go @@ -58,38 +58,38 @@ func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) { // files and number of processes to the maximum they can be set to // (without overriding a sysctl) if !nofileSet { - max := define.RLimitDefaultValue - current := define.RLimitDefaultValue + max := rlimT(define.RLimitDefaultValue) + current := rlimT(define.RLimitDefaultValue) if isRootless { var rlimit unix.Rlimit if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit); err != nil { logrus.Warnf("Failed to return RLIMIT_NOFILE ulimit %q", err) } - if rlimit.Cur < current { - current = rlimit.Cur + if rlimT(rlimit.Cur) < current { + current = rlimT(rlimit.Cur) } - if rlimit.Max < max { - max = rlimit.Max + if rlimT(rlimit.Max) < max { + max = rlimT(rlimit.Max) } } - g.AddProcessRlimits("RLIMIT_NOFILE", max, current) + g.AddProcessRlimits("RLIMIT_NOFILE", uint64(max), uint64(current)) } if !nprocSet { - max := define.RLimitDefaultValue - current := define.RLimitDefaultValue + max := rlimT(define.RLimitDefaultValue) + current := rlimT(define.RLimitDefaultValue) if isRootless { var rlimit unix.Rlimit if err := unix.Getrlimit(unix.RLIMIT_NPROC, &rlimit); err != nil { logrus.Warnf("Failed to return RLIMIT_NPROC ulimit %q", err) } - if rlimit.Cur < current { - current = rlimit.Cur + if rlimT(rlimit.Cur) < current { + current = rlimT(rlimit.Cur) } - if rlimit.Max < max { - max = rlimit.Max + if rlimT(rlimit.Max) < max { + max = rlimT(rlimit.Max) } } - g.AddProcessRlimits("RLIMIT_NPROC", max, current) + g.AddProcessRlimits("RLIMIT_NPROC", uint64(max), uint64(current)) } } diff --git a/pkg/specgen/generate/rlimit_int64.go b/pkg/specgen/generate/rlimit_int64.go new file mode 100644 index 000000000..b4cce3453 --- /dev/null +++ b/pkg/specgen/generate/rlimit_int64.go @@ -0,0 +1,6 @@ +//go:build freebsd +// +build freebsd + +package generate + +type rlimT int64 diff --git a/pkg/specgen/generate/rlimit_uint64.go b/pkg/specgen/generate/rlimit_uint64.go new file mode 100644 index 000000000..d85f8dd2c --- /dev/null +++ b/pkg/specgen/generate/rlimit_uint64.go @@ -0,0 +1,6 @@ +//go:build linux || darwin +// +build linux darwin + +package generate + +type rlimT uint64 |