diff options
Diffstat (limited to 'pkg')
44 files changed, 198 insertions, 175 deletions
diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go index 45b13818b..77fbbe38a 100644 --- a/pkg/api/handlers/compat/containers_archive.go +++ b/pkg/api/handlers/compat/containers_archive.go @@ -4,6 +4,7 @@ import ( "encoding/json" "net/http" "os" + "strings" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" @@ -94,11 +95,10 @@ func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.De func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) { query := struct { - Path string `schema:"path"` - Chown bool `schema:"copyUIDGID"` - Rename string `schema:"rename"` - // TODO handle params below - NoOverwriteDirNonDir bool `schema:"noOverwriteDirNonDir"` + Path string `schema:"path"` + Chown bool `schema:"copyUIDGID"` + Rename string `schema:"rename"` + NoOverwriteDirNonDir bool `schema:"noOverwriteDirNonDir"` }{ Chown: utils.IsLibpodRequest(r), // backward compatibility } @@ -112,7 +112,7 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, var rename map[string]string if query.Rename != "" { if err := json.Unmarshal([]byte(query.Rename), &rename); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query")) + utils.Error(w, http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query field 'rename'")) return } } @@ -120,15 +120,25 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, containerName := utils.GetName(r) containerEngine := abi.ContainerEngine{Libpod: runtime} - copyOptions := entities.CopyOptions{Chown: query.Chown, Rename: rename} - copyFunc, err := containerEngine.ContainerCopyFromArchive(r.Context(), containerName, query.Path, r.Body, copyOptions) - if errors.Cause(err) == define.ErrNoSuchCtr || os.IsNotExist(err) { - // 404 is returned for an absent container and path. The - // clients must deal with it accordingly. - utils.Error(w, http.StatusNotFound, errors.Wrap(err, "the container doesn't exists")) - return - } else if err != nil { - utils.Error(w, http.StatusInternalServerError, err) + copyFunc, err := containerEngine.ContainerCopyFromArchive(r.Context(), containerName, query.Path, r.Body, + entities.CopyOptions{ + Chown: query.Chown, + NoOverwriteDirNonDir: query.NoOverwriteDirNonDir, + Rename: rename, + }) + if err != nil { + switch { + case errors.Cause(err) == define.ErrNoSuchCtr || os.IsNotExist(err): + // 404 is returned for an absent container and path. The + // clients must deal with it accordingly. + utils.Error(w, http.StatusNotFound, errors.Wrap(err, "the container doesn't exists")) + case strings.Contains(err.Error(), "copier: put: error creating file"): + // Not the best test but need to break this out for compatibility + // See vendor/github.com/containers/buildah/copier/copier.go:1585 + utils.Error(w, http.StatusBadRequest, err) + default: + utils.Error(w, http.StatusInternalServerError, err) + } return } diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go index 8c4dea327..76a28fadf 100644 --- a/pkg/api/handlers/compat/images.go +++ b/pkg/api/handlers/compat/images.go @@ -460,8 +460,6 @@ func GetImages(w http.ResponseWriter, r *http.Request) { } func LoadImages(w http.ResponseWriter, r *http.Request) { - // TODO this is basically wrong - // TODO ... improve these ^ messages to something useful decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder) runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go index bcd102901..f47aa523e 100644 --- a/pkg/api/handlers/compat/images_build.go +++ b/pkg/api/handlers/compat/images_build.go @@ -80,6 +80,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { CgroupParent string `schema:"cgroupparent"` // nolint Compression uint64 `schema:"compression"` ConfigureNetwork string `schema:"networkmode"` + CPPFlags string `schema:"cppflags"` CpuPeriod uint64 `schema:"cpuperiod"` // nolint CpuQuota int64 `schema:"cpuquota"` // nolint CpuSetCpus string `schema:"cpusetcpus"` // nolint @@ -170,7 +171,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { // convert addcaps formats containerFiles := []string{} - // Tells if query paramemter `dockerfile` is set or not. + // Tells if query parameter `dockerfile` is set or not. dockerFileSet := false if utils.IsLibpodRequest(r) && query.Remote != "" { // The context directory could be a URL. Try to handle that. @@ -399,6 +400,15 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { } } + // convert cppflags formats + var cppflags = []string{} + if _, found := r.URL.Query()["cppflags"]; found { + if err := json.Unmarshal([]byte(query.CPPFlags), &cppflags); err != nil { + utils.BadRequest(w, "cppflags", query.CPPFlags, err) + return + } + } + // convert nsoptions formats nsoptions := buildah.NamespaceOptions{} if _, found := r.URL.Query()["nsoptions"]; found { @@ -555,6 +565,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { AddCapabilities: addCaps, AdditionalTags: additionalTags, Annotations: annotations, + CPPFlags: cppflags, Args: buildArgs, AllPlatforms: query.AllPlatforms, CommonBuildOpts: &buildah.CommonBuildOptions{ @@ -674,15 +685,17 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(body) enc.SetEscapeHTML(true) + var stepErrors []string for { - m := struct { + type BuildResponse struct { Stream string `json:"stream,omitempty"` Error *jsonmessage.JSONError `json:"errorDetail,omitempty"` // NOTE: `error` is being deprecated check https://github.com/moby/moby/blob/master/pkg/jsonmessage/jsonmessage.go#L148 ErrorMessage string `json:"error,omitempty"` // deprecate this slowly Aux json.RawMessage `json:"aux,omitempty"` - }{} + } + m := BuildResponse{} select { case e := <-stdout.Chan(): @@ -698,12 +711,27 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { } flush() case e := <-auxout.Chan(): - m.Stream = string(e) - if err := enc.Encode(m); err != nil { - stderr.Write([]byte(err.Error())) + if !query.Quiet { + m.Stream = string(e) + if err := enc.Encode(m); err != nil { + stderr.Write([]byte(err.Error())) + } + flush() + } else { + stepErrors = append(stepErrors, string(e)) } - flush() case e := <-stderr.Chan(): + // Docker-API Compat parity : Build failed so + // output all step errors irrespective of quiet + // flag. + for _, stepError := range stepErrors { + t := BuildResponse{} + t.Stream = stepError + if err := enc.Encode(t); err != nil { + stderr.Write([]byte(err.Error())) + } + flush() + } m.ErrorMessage = string(e) m.Error = &jsonmessage.JSONError{ Message: m.ErrorMessage, diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go index 419225007..3a78436d7 100644 --- a/pkg/auth/auth.go +++ b/pkg/auth/auth.go @@ -245,8 +245,6 @@ func authConfigsToAuthFile(authConfigs map[string]types.DockerAuthConfig) (strin } authFilePath := tmpFile.Name() - // TODO: It would be nice if c/image could dump the map at once. - // // Now use the c/image packages to store the credentials. It's battle // tested, and we make sure to use the same code as the image backend. sys := types.SystemContext{AuthFilePath: authFilePath} diff --git a/pkg/bindings/containers/archive.go b/pkg/bindings/containers/archive.go index 4f4b5a36a..dd489d6f1 100644 --- a/pkg/bindings/containers/archive.go +++ b/pkg/bindings/containers/archive.go @@ -55,8 +55,6 @@ func CopyFromArchive(ctx context.Context, nameOrID string, path string, reader i } // CopyFromArchiveWithOptions copy files into container -// -// FIXME: remove this function and make CopyFromArchive accept the option as the last parameter in podman 4.0 func CopyFromArchiveWithOptions(ctx context.Context, nameOrID string, path string, reader io.Reader, options *CopyOptions) (entities.ContainerCopyFunc, error) { conn, err := bindings.GetClient(ctx) if err != nil { diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go index 51dcd2aa5..b4b7c36f6 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -65,6 +65,14 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO params.Set("annotations", l) } + if cppflags := options.CPPFlags; len(cppflags) > 0 { + l, err := jsoniter.MarshalToString(cppflags) + if err != nil { + return nil, err + } + params.Set("cppflags", l) + } + if options.AllPlatforms { params.Add("allplatforms", "1") } diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go index 8e3b07929..32372019b 100644 --- a/pkg/bindings/images/images.go +++ b/pkg/bindings/images/images.go @@ -280,7 +280,6 @@ func Push(ctx context.Context, source string, destination string, options *PushO if err != nil { return err } - // TODO: have a global system context we can pass around (1st argument) header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword()) if err != nil { return err @@ -329,7 +328,6 @@ func Search(ctx context.Context, term string, options *SearchOptions) ([]entitie params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify())) } - // TODO: have a global system context we can pass around (1st argument) header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, "", "") if err != nil { return nil, err diff --git a/pkg/bindings/images/pull.go b/pkg/bindings/images/pull.go index 20e47179c..de02c62fd 100644 --- a/pkg/bindings/images/pull.go +++ b/pkg/bindings/images/pull.go @@ -42,7 +42,6 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string, params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify())) } - // TODO: have a global system context we can pass around (1st argument) header, err := auth.MakeXRegistryAuthHeader(&types.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword()) if err != nil { return nil, err diff --git a/pkg/bindings/images/rm.go b/pkg/bindings/images/rm.go index b80bacf45..eb3eef10c 100644 --- a/pkg/bindings/images/rm.go +++ b/pkg/bindings/images/rm.go @@ -16,9 +16,6 @@ func Remove(ctx context.Context, images []string, options *RemoveOptions) (*enti if options == nil { options = new(RemoveOptions) } - // FIXME - bindings tests are missing for this endpoint. Once the CI is - // re-enabled for bindings, we need to add them. At the time of writing, - // the tests don't compile. var report types.LibpodImagesRemoveReport conn, err := bindings.GetClient(ctx) if err != nil { diff --git a/pkg/bindings/play/play.go b/pkg/bindings/play/play.go index 8058a8514..0261b0250 100644 --- a/pkg/bindings/play/play.go +++ b/pkg/bindings/play/play.go @@ -46,7 +46,6 @@ func KubeWithBody(ctx context.Context, body io.Reader, options *KubeOptions) (*e params.Set("start", strconv.FormatBool(options.GetStart())) } - // TODO: have a global system context we can pass around (1st argument) header, err := auth.MakeXRegistryAuthHeader(&types.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword()) if err != nil { return nil, err diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go index 1db8b9951..37711ca58 100644 --- a/pkg/domain/entities/containers.go +++ b/pkg/domain/entities/containers.go @@ -47,8 +47,7 @@ type ContainerRunlabelOptions struct { } // ContainerRunlabelReport contains the results from executing container-runlabel. -type ContainerRunlabelReport struct { -} +type ContainerRunlabelReport struct{} type WaitOptions struct { Condition []define.ContainerStatus @@ -165,6 +164,9 @@ type CopyOptions struct { Chown bool // Map to translate path names. Rename map[string]string + // NoOverwriteDirNonDir when true prevents an existing directory or file from being overwritten + // by the other type + NoOverwriteDirNonDir bool } type CommitReport struct { diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index 7081c5d25..2bb4ceb5b 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -66,10 +66,9 @@ type ImageSummary struct { Dangling bool `json:",omitempty"` // Podman extensions - Names []string `json:",omitempty"` - Digest string `json:",omitempty"` - ConfigDigest string `json:",omitempty"` - History []string `json:",omitempty"` + Names []string `json:",omitempty"` + Digest string `json:",omitempty"` + History []string `json:",omitempty"` } func (i *ImageSummary) Id() string { // nolint @@ -398,7 +397,6 @@ type ImageUnmountOptions struct { // ImageMountReport describes the response from image mount type ImageMountReport struct { - Err error Id string // nolint Name string Repositories []string diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go index 5ae8a4931..3e6e54e7d 100644 --- a/pkg/domain/entities/types.go +++ b/pkg/domain/entities/types.go @@ -78,10 +78,9 @@ type InspectOptions struct { // DiffOptions all API and CLI diff commands and diff sub-commands use the same options type DiffOptions struct { - Format string `json:",omitempty"` // CLI only - Latest bool `json:",omitempty"` // API and CLI, only supported by containers - Archive bool `json:",omitempty"` // CLI only - Type define.DiffType // Type which should be compared + Format string `json:",omitempty"` // CLI only + Latest bool `json:",omitempty"` // API and CLI, only supported by containers + Type define.DiffType // Type which should be compared } // DiffReport provides changes for object diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go index 3e5b9cad9..e2ab8d70c 100644 --- a/pkg/domain/filters/containers.go +++ b/pkg/domain/filters/containers.go @@ -6,6 +6,7 @@ import ( "strings" "time" + cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/util" @@ -257,7 +258,7 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo return false } for _, net := range networks { - if util.StringInSlice(net, inputNetNames) { + if cutil.StringInSlice(net, inputNetNames) { return true } } diff --git a/pkg/domain/filters/pods.go b/pkg/domain/filters/pods.go index e22480006..c2ed359f5 100644 --- a/pkg/domain/filters/pods.go +++ b/pkg/domain/filters/pods.go @@ -4,6 +4,7 @@ import ( "strconv" "strings" + cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/util" @@ -57,7 +58,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti }, nil case "ctr-status": for _, filterValue := range filterValues { - if !util.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) { + if !cutil.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) { return nil, errors.Errorf("%s is not a valid status", filterValue) } } @@ -94,7 +95,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti }, nil case "status": for _, filterValue := range filterValues { - if !util.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created", "degraded"}) { + if !cutil.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created", "degraded"}) { return nil, errors.Errorf("%s is not a valid pod status", filterValue) } } @@ -150,7 +151,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti return false } for _, net := range networks { - if util.StringInSlice(net, inputNetNames) { + if cutil.StringInSlice(net, inputNetNames) { return true } } diff --git a/pkg/domain/infra/abi/archive.go b/pkg/domain/infra/abi/archive.go index 01e3c7dd1..de96cf8b0 100644 --- a/pkg/domain/infra/abi/archive.go +++ b/pkg/domain/infra/abi/archive.go @@ -12,10 +12,10 @@ func (ic *ContainerEngine) ContainerCopyFromArchive(ctx context.Context, nameOrI if err != nil { return nil, err } - return container.CopyFromArchive(ctx, containerPath, options.Chown, options.Rename, reader) + return container.CopyFromArchive(ctx, containerPath, options.Chown, options.NoOverwriteDirNonDir, options.Rename, reader) } -func (ic *ContainerEngine) ContainerCopyToArchive(ctx context.Context, nameOrID string, containerPath string, writer io.Writer) (entities.ContainerCopyFunc, error) { +func (ic *ContainerEngine) ContainerCopyToArchive(ctx context.Context, nameOrID, containerPath string, writer io.Writer) (entities.ContainerCopyFunc, error) { container, err := ic.Libpod.LookupContainer(nameOrID) if err != nil { return nil, err diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index c3ec7dd8a..d469fa0ca 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -159,10 +159,6 @@ func (ir *ImageEngine) Mount(ctx context.Context, nameOrIDs []string, opts entit mountReports := []*entities.ImageMountReport{} listMountsOnly := !opts.All && len(nameOrIDs) == 0 for _, i := range images { - // TODO: the .Err fields are not used. This pre-dates the - // libimage migration but should be addressed at some point. - // A quick glimpse at cmd/podman/image/mount.go suggests that - // the errors needed to be handled there as well. var mountPoint string var err error if listMountsOnly { diff --git a/pkg/domain/infra/abi/images_list.go b/pkg/domain/infra/abi/images_list.go index 9a0aaaf3a..8f5591e92 100644 --- a/pkg/domain/infra/abi/images_list.go +++ b/pkg/domain/infra/abi/images_list.go @@ -36,9 +36,7 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) } e := entities.ImageSummary{ - ID: img.ID(), - // TODO: libpod/image didn't set it but libimage should - // ConfigDigest: string(img.ConfigDigest), + ID: img.ID(), Created: img.Created().Unix(), Dangling: isDangling, Digest: string(img.Digest()), diff --git a/pkg/domain/infra/abi/images_test.go b/pkg/domain/infra/abi/images_test.go index 311ab3ed7..3999de457 100644 --- a/pkg/domain/infra/abi/images_test.go +++ b/pkg/domain/infra/abi/images_test.go @@ -16,39 +16,3 @@ func TestToDomainHistoryLayer(t *testing.T) { newLayer := toDomainHistoryLayer(&layer) assert.Equal(t, layer.Size, newLayer.Size) } - -// -// import ( -// "context" -// "testing" -// -// "github.com/stretchr/testify/mock" -// ) -// -// type MockImageRuntime struct { -// mock.Mock -// } -// -// func (m *MockImageRuntime) Delete(ctx context.Context, renderer func() interface{}, name string) error { -// _ = m.Called(ctx, renderer, name) -// return nil -// } -// -// func TestImageSuccess(t *testing.T) { -// actual := func() interface{} { return nil } -// -// m := new(MockImageRuntime) -// m.On( -// "Delete", -// mock.AnythingOfType("*context.emptyCtx"), -// mock.AnythingOfType("func() interface {}"), -// "fedora"). -// Return(nil) -// -// r := DirectImageRuntime{m} -// err := r.Delete(context.TODO(), actual, "fedora") -// if err != nil { -// t.Errorf("should be nil, got: %v", err) -// } -// m.AssertExpectations(t) -// } diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go index 910008fc7..47f7917f4 100644 --- a/pkg/domain/infra/abi/network.go +++ b/pkg/domain/infra/abi/network.go @@ -5,9 +5,9 @@ import ( "github.com/containers/common/libnetwork/types" netutil "github.com/containers/common/libnetwork/util" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/domain/entities" - "github.com/containers/podman/v4/pkg/util" "github.com/pkg/errors" ) diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index 10f3e70b1..2ce190464 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -10,6 +10,7 @@ import ( "github.com/containers/common/pkg/cgroups" "github.com/containers/common/pkg/config" + cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/entities/reports" @@ -307,7 +308,7 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System reclaimableSize += volSize } for _, viu := range inUse { - if util.StringInSlice(viu, runningContainers) { + if cutil.StringInSlice(viu, runningContainers) { consInUse++ } } diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go index ac557e9de..daa6f0cbf 100644 --- a/pkg/domain/infra/runtime_libpod.go +++ b/pkg/domain/infra/runtime_libpod.go @@ -9,9 +9,9 @@ import ( "os" "os/signal" "sync" + "syscall" "github.com/containers/common/pkg/cgroups" - "github.com/containers/podman/v4/cmd/podman/utils" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/namespaces" @@ -375,7 +375,7 @@ func ParseIDMapping(mode namespaces.UsernsMode, uidMapSlice, gidMapSlice []strin func StartWatcher(rt *libpod.Runtime) { // Setup the signal notifier ch := make(chan os.Signal, 1) - signal.Notify(ch, utils.SIGHUP) + signal.Notify(ch, syscall.SIGHUP) go func() { for { diff --git a/pkg/inspect/inspect.go b/pkg/inspect/inspect.go index 767d86daf..15943858f 100644 --- a/pkg/inspect/inspect.go +++ b/pkg/inspect/inspect.go @@ -41,18 +41,3 @@ type RootFS struct { Type string `json:"Type"` Layers []digest.Digest `json:"Layers"` } - -// ImageResult is used for podman images for collection and output. -type ImageResult struct { - Tag string - Repository string - RepoDigests []string - RepoTags []string - ID string - Digest digest.Digest - ConfigDigest digest.Digest - Created time.Time - Size *uint64 - Labels map[string]string - Dangling bool -} diff --git a/pkg/machine/config.go b/pkg/machine/config.go index d34776714..abbebc9f9 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -138,14 +138,15 @@ type DistributionDownload interface { Get() *Download } type InspectInfo struct { - ConfigPath VMFile - Created time.Time - Image ImageConfig - LastUp time.Time - Name string - Resources ResourceConfig - SSHConfig SSHConfig - State Status + ConfigPath VMFile + ConnectionInfo ConnectionConfig + Created time.Time + Image ImageConfig + LastUp time.Time + Name string + Resources ResourceConfig + SSHConfig SSHConfig + State Status } func (rc RemoteConnectionType) MakeSSHURL(host, path, port, userName string) url.URL { @@ -286,11 +287,11 @@ func NewMachineFile(path string, symlink *string) (*VMFile, error) { // makeSymlink for macOS creates a symlink in $HOME/.podman/ // for a machinefile like a socket func (m *VMFile) makeSymlink(symlink *string) error { - homedir, err := os.UserHomeDir() + homeDir, err := os.UserHomeDir() if err != nil { return err } - sl := filepath.Join(homedir, ".podman", *symlink) + sl := filepath.Join(homeDir, ".podman", *symlink) // make the symlink dir and throw away if it already exists if err := os.MkdirAll(filepath.Dir(sl), 0700); err != nil && !errors2.Is(err, os.ErrNotExist) { return err @@ -335,3 +336,9 @@ type SSHConfig struct { // RemoteUsername of the vm user RemoteUsername string } + +// ConnectionConfig contains connections like sockets, etc. +type ConnectionConfig struct { + // PodmanSocket is the exported podman service socket + PodmanSocket *VMFile `json:"PodmanSocket"` +} diff --git a/pkg/machine/e2e/config.go b/pkg/machine/e2e/config.go index c17b840d3..248a2f0ad 100644 --- a/pkg/machine/e2e/config.go +++ b/pkg/machine/e2e/config.go @@ -85,6 +85,14 @@ func (ms *machineSession) outputToString() string { return strings.Join(fields, " ") } +// errorToString returns the error output from a session in string form +func (ms *machineSession) errorToString() string { + if ms == nil || ms.Err == nil || ms.Err.Contents() == nil { + return "" + } + return string(ms.Err.Contents()) +} + // newMB constructor for machine test builders func newMB() (*machineTestBuilder, error) { mb := machineTestBuilder{ diff --git a/pkg/machine/e2e/inspect_test.go b/pkg/machine/e2e/inspect_test.go index 2c9de5664..cdf13bb1a 100644 --- a/pkg/machine/e2e/inspect_test.go +++ b/pkg/machine/e2e/inspect_test.go @@ -2,6 +2,7 @@ package e2e import ( "encoding/json" + "strings" "github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine/qemu" @@ -86,6 +87,7 @@ var _ = Describe("podman machine stop", func() { var inspectInfo []machine.InspectInfo err = jsoniter.Unmarshal(inspectSession.Bytes(), &inspectInfo) Expect(err).To(BeNil()) + Expect(strings.HasSuffix(inspectInfo[0].ConnectionInfo.PodmanSocket.GetPath(), "podman.sock")) inspect := new(inspectMachine) inspect = inspect.withFormat("{{.Name}}") diff --git a/pkg/machine/e2e/list_test.go b/pkg/machine/e2e/list_test.go index 0bc867047..1c8c6ac81 100644 --- a/pkg/machine/e2e/list_test.go +++ b/pkg/machine/e2e/list_test.go @@ -3,7 +3,7 @@ package e2e import ( "strings" - "github.com/containers/buildah/util" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/cmd/podman/machine" jsoniter "github.com/json-iterator/go" . "github.com/onsi/ginkgo" diff --git a/pkg/machine/e2e/ssh_test.go b/pkg/machine/e2e/ssh_test.go index 155d39a64..9ee31ac26 100644 --- a/pkg/machine/e2e/ssh_test.go +++ b/pkg/machine/e2e/ssh_test.go @@ -56,5 +56,12 @@ var _ = Describe("podman machine ssh", func() { Expect(err).To(BeNil()) Expect(sshSession).To(Exit(0)) Expect(sshSession.outputToString()).To(ContainSubstring("Fedora CoreOS")) + + // keep exit code + sshSession, err = mb.setName(name).setCmd(ssh.withSSHComand([]string{"false"})).run() + Expect(err).To(BeNil()) + Expect(sshSession).To(Exit(1)) + Expect(sshSession.outputToString()).To(Equal("")) + Expect(sshSession.errorToString()).To(Equal("")) }) }) diff --git a/pkg/machine/fcos.go b/pkg/machine/fcos.go index df58b8a1e..77427139a 100644 --- a/pkg/machine/fcos.go +++ b/pkg/machine/fcos.go @@ -146,13 +146,6 @@ func GetFCOSDownload(imageStream string) (*FcosDownloadInfo, error) { //nolint:s streamType string ) - // This is being hard set to testing. Once podman4 is in the - // fcos trees, we should remove it and re-release at least on - // macs. - // TODO: remove when podman4.0 is in coreos - - imageStream = "podman-testing" //nolint:staticcheck - switch imageStream { case "podman-testing": streamType = "podman-testing" diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 6e36b0886..b9f23662e 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -952,7 +952,8 @@ func (v *MachineVM) SSH(_ string, opts machine.SSHOptions) error { sshDestination := username + "@localhost" port := strconv.Itoa(v.Port) - args := []string{"-i", v.IdentityPath, "-p", port, sshDestination, "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no"} + args := []string{"-i", v.IdentityPath, "-p", port, sshDestination, "-o", "UserKnownHostsFile=/dev/null", + "-o", "StrictHostKeyChecking=no", "-o", "LogLevel=ERROR"} if len(opts.Args) > 0 { args = append(args, opts.Args...) } else { @@ -1471,16 +1472,22 @@ func (v *MachineVM) Inspect() (*machine.InspectInfo, error) { if err != nil { return nil, err } - + connInfo := new(machine.ConnectionConfig) + podmanSocket, err := v.forwardSocketPath() + if err != nil { + return nil, err + } + connInfo.PodmanSocket = podmanSocket return &machine.InspectInfo{ - ConfigPath: v.ConfigPath, - Created: v.Created, - Image: v.ImageConfig, - LastUp: v.LastUp, - Name: v.Name, - Resources: v.ResourceConfig, - SSHConfig: v.SSHConfig, - State: state, + ConfigPath: v.ConfigPath, + ConnectionInfo: *connInfo, + Created: v.Created, + Image: v.ImageConfig, + LastUp: v.LastUp, + Name: v.Name, + Resources: v.ResourceConfig, + SSHConfig: v.SSHConfig, + State: state, }, nil } @@ -1545,7 +1552,7 @@ func (v *MachineVM) editCmdLine(flag string, value string) { } } -// RemoveAndCleanMachines removes all machine and cleans up any other files associatied with podman machine +// RemoveAndCleanMachines removes all machine and cleans up any other files associated with podman machine func (p *Provider) RemoveAndCleanMachines() error { var ( vm machine.VM diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go index 0b2874baf..06020aded 100644 --- a/pkg/machine/wsl/machine.go +++ b/pkg/machine/wsl/machine.go @@ -831,16 +831,16 @@ func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) { } if opts.CPUs != nil { - setErrors = append(setErrors, errors.Errorf("changing CPUs not suppored for WSL machines")) + setErrors = append(setErrors, errors.Errorf("changing CPUs not supported for WSL machines")) } if opts.Memory != nil { - setErrors = append(setErrors, errors.Errorf("changing memory not suppored for WSL machines")) + setErrors = append(setErrors, errors.Errorf("changing memory not supported for WSL machines")) } if opts.DiskSize != nil { - setErrors = append(setErrors, errors.Errorf("changing Disk Size not suppored for WSL machines")) + setErrors = append(setErrors, errors.Errorf("changing Disk Size not supported for WSL machines")) } return setErrors, v.writeConfig() @@ -1477,7 +1477,7 @@ func (v *MachineVM) getResources() (resources machine.ResourceConfig) { return } -// RemoveAndCleanMachines removes all machine and cleans up any other files associatied with podman machine +// RemoveAndCleanMachines removes all machine and cleans up any other files associated with podman machine func (p *Provider) RemoveAndCleanMachines() error { var ( vm machine.VM diff --git a/pkg/signal/signal_common.go b/pkg/signal/signal_common.go index 5ea67843a..fe5a76dae 100644 --- a/pkg/signal/signal_common.go +++ b/pkg/signal/signal_common.go @@ -17,7 +17,7 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) { } return syscall.Signal(s), nil } - sig, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")] + sig, ok := SignalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")] if !ok { return -1, fmt.Errorf("invalid signal: %s", rawSignal) } @@ -32,7 +32,7 @@ func ParseSignalNameOrNumber(rawSignal string) (syscall.Signal, error) { if err == nil { return s, nil } - for k, v := range signalMap { + for k, v := range SignalMap { if k == strings.ToUpper(basename) { return v, nil } diff --git a/pkg/signal/signal_linux.go b/pkg/signal/signal_linux.go index 21e09c9fe..a114ea019 100644 --- a/pkg/signal/signal_linux.go +++ b/pkg/signal/signal_linux.go @@ -23,8 +23,8 @@ const ( SIGWINCH = syscall.SIGWINCH // For cross-compilation with Windows ) -// signalMap is a map of Linux signals. -var signalMap = map[string]syscall.Signal{ +// SignalMap is a map of Linux signals. +var SignalMap = map[string]syscall.Signal{ "ABRT": unix.SIGABRT, "ALRM": unix.SIGALRM, "BUS": unix.SIGBUS, @@ -94,8 +94,8 @@ var signalMap = map[string]syscall.Signal{ // CatchAll catches all signals and relays them to the specified channel. func CatchAll(sigc chan os.Signal) { - handledSigs := make([]os.Signal, 0, len(signalMap)) - for _, s := range signalMap { + handledSigs := make([]os.Signal, 0, len(SignalMap)) + for _, s := range SignalMap { handledSigs = append(handledSigs, s) } signal.Notify(sigc, handledSigs...) diff --git a/pkg/signal/signal_linux_mipsx.go b/pkg/signal/signal_linux_mipsx.go index 52b07aaf4..9021a10e7 100644 --- a/pkg/signal/signal_linux_mipsx.go +++ b/pkg/signal/signal_linux_mipsx.go @@ -24,8 +24,8 @@ const ( SIGWINCH = syscall.SIGWINCH ) -// signalMap is a map of Linux signals. -var signalMap = map[string]syscall.Signal{ +// SignalMap is a map of Linux signals. +var SignalMap = map[string]syscall.Signal{ "ABRT": unix.SIGABRT, "ALRM": unix.SIGALRM, "BUS": unix.SIGBUS, @@ -95,8 +95,8 @@ var signalMap = map[string]syscall.Signal{ // CatchAll catches all signals and relays them to the specified channel. func CatchAll(sigc chan os.Signal) { - handledSigs := make([]os.Signal, 0, len(signalMap)) - for _, s := range signalMap { + handledSigs := make([]os.Signal, 0, len(SignalMap)) + for _, s := range SignalMap { handledSigs = append(handledSigs, s) } signal.Notify(sigc, handledSigs...) diff --git a/pkg/signal/signal_unix.go b/pkg/signal/signal_unix.go index c0aa62d21..0f43e21b7 100644 --- a/pkg/signal/signal_unix.go +++ b/pkg/signal/signal_unix.go @@ -16,12 +16,12 @@ const ( SIGWINCH = syscall.SIGWINCH ) -// signalMap is a map of Linux signals. +// SignalMap is a map of Linux signals. // These constants are sourced from the Linux version of golang.org/x/sys/unix // (I don't see much risk of this changing). // This should work as long as Podman only runs containers on Linux, which seems // a safe assumption for now. -var signalMap = map[string]syscall.Signal{ +var SignalMap = map[string]syscall.Signal{ "ABRT": syscall.Signal(0x6), "ALRM": syscall.Signal(0xe), "BUS": syscall.Signal(0x7), diff --git a/pkg/signal/signal_unsupported.go b/pkg/signal/signal_unsupported.go index d8bba7c90..9d0cee317 100644 --- a/pkg/signal/signal_unsupported.go +++ b/pkg/signal/signal_unsupported.go @@ -16,12 +16,12 @@ const ( SIGWINCH = syscall.Signal(0xff) ) -// signalMap is a map of Linux signals. +// SignalMap is a map of Linux signals. // These constants are sourced from the Linux version of golang.org/x/sys/unix // (I don't see much risk of this changing). // This should work as long as Podman only runs containers on Linux, which seems // a safe assumption for now. -var signalMap = map[string]syscall.Signal{ +var SignalMap = map[string]syscall.Signal{ "ABRT": syscall.Signal(0x6), "ALRM": syscall.Signal(0xe), "BUS": syscall.Signal(0x7), diff --git a/pkg/specgen/container_validate.go b/pkg/specgen/container_validate.go index 355fbc368..532a2094f 100644 --- a/pkg/specgen/container_validate.go +++ b/pkg/specgen/container_validate.go @@ -4,9 +4,9 @@ import ( "strconv" "strings" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/rootless" - "github.com/containers/podman/v4/pkg/util" "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" ) diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index f37d79798..689c740f0 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -16,6 +16,7 @@ import ( "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/parse" "github.com/containers/common/pkg/secrets" + cutil "github.com/containers/common/pkg/util" "github.com/containers/image/v5/manifest" "github.com/containers/podman/v4/libpod/define" ann "github.com/containers/podman/v4/pkg/annotations" @@ -356,7 +357,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener // a selinux mount option exists for it for k, v := range opts.Annotations { // Make sure the z/Z option is not already there (from editing the YAML) - if strings.Replace(k, define.BindMountPrefix, "", 1) == volumeSource.Source && !util.StringInSlice("z", options) && !util.StringInSlice("Z", options) { + if strings.Replace(k, define.BindMountPrefix, "", 1) == volumeSource.Source && !cutil.StringInSlice("z", options) && !cutil.StringInSlice("Z", options) { options = append(options, v) } } diff --git a/pkg/specgen/generate/ports.go b/pkg/specgen/generate/ports.go index bec548d3b..4243630e2 100644 --- a/pkg/specgen/generate/ports.go +++ b/pkg/specgen/generate/ports.go @@ -10,9 +10,9 @@ import ( "github.com/containers/common/libnetwork/types" "github.com/containers/podman/v4/utils" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/pkg/specgenutil" - "github.com/containers/podman/v4/pkg/util" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go index ec52164ab..7268ec318 100644 --- a/pkg/specgen/generate/security.go +++ b/pkg/specgen/generate/security.go @@ -7,6 +7,7 @@ import ( "github.com/containers/common/pkg/apparmor" "github.com/containers/common/pkg/capabilities" "github.com/containers/common/pkg/config" + cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/specgen" @@ -120,7 +121,7 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, // capabilities, required to run the container. var capsRequiredRequested []string for key, val := range s.Labels { - if util.StringInSlice(key, capabilities.ContainerImageLabels) { + if cutil.StringInSlice(key, capabilities.ContainerImageLabels) { capsRequiredRequested = strings.Split(val, ",") } } @@ -132,7 +133,7 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, } // Verify all capRequired are in the capList for _, cap := range capsRequired { - if !util.StringInSlice(cap, caplist) { + if !cutil.StringInSlice(cap, caplist) { privCapsRequired = append(privCapsRequired, cap) } } diff --git a/pkg/specgen/generate/validate.go b/pkg/specgen/generate/validate.go index 44c7818e7..a1affef31 100644 --- a/pkg/specgen/generate/validate.go +++ b/pkg/specgen/generate/validate.go @@ -1,6 +1,7 @@ package generate import ( + "io/ioutil" "os" "path/filepath" @@ -166,6 +167,14 @@ func verifyContainerResourcesCgroupV2(s *specgen.SpecGenerator) ([]string, error if err != nil { return warnings, err } + + if own == "/" { + // If running under the root cgroup try to create or reuse a "probe" cgroup to read memory values + own = "podman_probe" + _ = os.MkdirAll(filepath.Join("/sys/fs/cgroup", own), 0o755) + _ = ioutil.WriteFile("/sys/fs/cgroup/cgroup.subtree_control", []byte("+memory"), 0o644) + } + memoryMax := filepath.Join("/sys/fs/cgroup", own, "memory.max") memorySwapMax := filepath.Join("/sys/fs/cgroup", own, "memory.swap.max") _, errMemoryMax := os.Stat(memoryMax) diff --git a/pkg/specgen/namespaces.go b/pkg/specgen/namespaces.go index 7a7ca2706..5a3b94ca4 100644 --- a/pkg/specgen/namespaces.go +++ b/pkg/specgen/namespaces.go @@ -8,6 +8,7 @@ import ( "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/cgroups" + cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/podman/v4/pkg/util" @@ -472,7 +473,7 @@ func ParseNetworkFlag(networks []string) (Namespace, map[string]types.PerNetwork if parts[0] == "" { return toReturn, nil, nil, errors.Wrapf(define.ErrInvalidArg, "network name cannot be empty") } - if util.StringInSlice(parts[0], []string{string(Bridge), string(Slirp), string(FromPod), string(NoNetwork), + if cutil.StringInSlice(parts[0], []string{string(Bridge), string(Slirp), string(FromPod), string(NoNetwork), string(Default), string(Private), string(Path), string(FromContainer), string(Host)}) { return toReturn, nil, nil, errors.Wrapf(define.ErrInvalidArg, "can only set extra network names, selected mode %s conflicts with bridge", parts[0]) } diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go index 9cb2f200b..efaade9cd 100644 --- a/pkg/specgenutil/specgen.go +++ b/pkg/specgenutil/specgen.go @@ -622,7 +622,14 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions if opt == "no-new-privileges" { s.ContainerSecurityConfig.NoNewPrivileges = true } else { - con := strings.SplitN(opt, "=", 2) + // Docker deprecated the ":" syntax but still supports it, + // so we need to as well + var con []string + if strings.Contains(opt, "=") { + con = strings.SplitN(opt, "=", 2) + } else { + con = strings.SplitN(opt, ":", 2) + } if len(con) != 2 { return fmt.Errorf("invalid --security-opt 1: %q", opt) } @@ -650,6 +657,12 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions } case "unmask": s.ContainerSecurityConfig.Unmask = append(s.ContainerSecurityConfig.Unmask, con[1:]...) + case "no-new-privileges": + noNewPrivileges, err := strconv.ParseBool(con[1]) + if err != nil { + return fmt.Errorf("invalid --security-opt 2: %q", opt) + } + s.ContainerSecurityConfig.NoNewPrivileges = noNewPrivileges default: return fmt.Errorf("invalid --security-opt 2: %q", opt) } diff --git a/pkg/util/utils.go b/pkg/util/utils.go index a0bf8b50d..ad5db9a1a 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -17,6 +17,7 @@ import ( "github.com/BurntSushi/toml" "github.com/containers/common/pkg/config" + "github.com/containers/common/pkg/util" "github.com/containers/image/v5/types" "github.com/containers/podman/v4/pkg/errorhandling" "github.com/containers/podman/v4/pkg/namespaces" @@ -78,14 +79,9 @@ func ParseRegistryCreds(creds string) (*types.DockerAuthConfig, error) { }, nil } -// StringInSlice determines if a string is in a string slice, returns bool +// StringInSlice is deprecated, use containers/common/pkg/util/StringInSlice func StringInSlice(s string, sl []string) bool { - for _, i := range sl { - if i == s { - return true - } - } - return false + return util.StringInSlice(s, sl) } // StringMatchRegexSlice determines if a given string matches one of the given regexes, returns bool |