diff options
Diffstat (limited to 'pkg')
99 files changed, 514 insertions, 297 deletions
diff --git a/pkg/annotations/annotations.go b/pkg/annotations/annotations.go index 8badab20d..a22222f10 100644 --- a/pkg/annotations/annotations.go +++ b/pkg/annotations/annotations.go @@ -1,122 +1,122 @@ package annotations const ( - // Annotations carries the received Kubelet annotations + // Annotations carries the received Kubelet annotations. Annotations = "io.kubernetes.cri-o.Annotations" - // ContainerID is the container ID annotation + // ContainerID is the container ID annotation. ContainerID = "io.kubernetes.cri-o.ContainerID" - // ContainerName is the container name annotation + // ContainerName is the container name annotation. ContainerName = "io.kubernetes.cri-o.ContainerName" - // ContainerType is the container type (sandbox or container) annotation + // ContainerType is the container type (sandbox or container) annotation. ContainerType = "io.kubernetes.cri-o.ContainerType" - // Created is the container creation time annotation + // Created is the container creation time annotation. Created = "io.kubernetes.cri-o.Created" - // HostName is the container host name annotation + // HostName is the container host name annotation. HostName = "io.kubernetes.cri-o.HostName" - // CgroupParent is the sandbox cgroup parent + // CgroupParent is the sandbox cgroup parent. CgroupParent = "io.kubernetes.cri-o.CgroupParent" - // IP is the container ipv4 or ipv6 address + // IP is the container ipv4 or ipv6 address. IP = "io.kubernetes.cri-o.IP" - // NamespaceOptions store the options for namespaces + // NamespaceOptions store the options for namespaces. NamespaceOptions = "io.kubernetes.cri-o.NamespaceOptions" - // SeccompProfilePath is the node seccomp profile path + // SeccompProfilePath is the node seccomp profile path. SeccompProfilePath = "io.kubernetes.cri-o.SeccompProfilePath" - // Image is the container image ID annotation + // Image is the container image ID annotation. Image = "io.kubernetes.cri-o.Image" - // ImageName is the container image name annotation + // ImageName is the container image name annotation. ImageName = "io.kubernetes.cri-o.ImageName" - // ImageRef is the container image ref annotation + // ImageRef is the container image ref annotation. ImageRef = "io.kubernetes.cri-o.ImageRef" - // KubeName is the kubernetes name annotation + // KubeName is the kubernetes name annotation. KubeName = "io.kubernetes.cri-o.KubeName" - // PortMappings holds the port mappings for the sandbox + // PortMappings holds the port mappings for the sandbox. PortMappings = "io.kubernetes.cri-o.PortMappings" - // Labels are the kubernetes labels annotation + // Labels are the kubernetes labels annotation. Labels = "io.kubernetes.cri-o.Labels" - // LogPath is the container logging path annotation + // LogPath is the container logging path annotation. LogPath = "io.kubernetes.cri-o.LogPath" - // Metadata is the container metadata annotation + // Metadata is the container metadata annotation. Metadata = "io.kubernetes.cri-o.Metadata" - // Name is the pod name annotation + // Name is the pod name annotation. Name = "io.kubernetes.cri-o.Name" - // Namespace is the pod namespace annotation + // Namespace is the pod namespace annotation. Namespace = "io.kubernetes.cri-o.Namespace" - // PrivilegedRuntime is the annotation for the privileged runtime path + // PrivilegedRuntime is the annotation for the privileged runtime path. PrivilegedRuntime = "io.kubernetes.cri-o.PrivilegedRuntime" - // ResolvPath is the resolver configuration path annotation + // ResolvPath is the resolver configuration path annotation. ResolvPath = "io.kubernetes.cri-o.ResolvPath" - // HostnamePath is the path to /etc/hostname to bind mount annotation + // HostnamePath is the path to /etc/hostname to bind mount annotation. HostnamePath = "io.kubernetes.cri-o.HostnamePath" - // SandboxID is the sandbox ID annotation + // SandboxID is the sandbox ID annotation. SandboxID = "io.kubernetes.cri-o.SandboxID" - // SandboxName is the sandbox name annotation + // SandboxName is the sandbox name annotation. SandboxName = "io.kubernetes.cri-o.SandboxName" - // ShmPath is the shared memory path annotation + // ShmPath is the shared memory path annotation. ShmPath = "io.kubernetes.cri-o.ShmPath" - // MountPoint is the mount point of the container rootfs + // MountPoint is the mount point of the container rootfs. MountPoint = "io.kubernetes.cri-o.MountPoint" - // RuntimeHandler is the annotation for runtime handler + // RuntimeHandler is the annotation for runtime handler. RuntimeHandler = "io.kubernetes.cri-o.RuntimeHandler" - // TTY is the terminal path annotation + // TTY is the terminal path annotation. TTY = "io.kubernetes.cri-o.TTY" - // Stdin is the stdin annotation + // Stdin is the stdin annotation. Stdin = "io.kubernetes.cri-o.Stdin" - // StdinOnce is the stdin_once annotation + // StdinOnce is the stdin_once annotation. StdinOnce = "io.kubernetes.cri-o.StdinOnce" - // Volumes is the volumes annotation + // Volumes is the volumes annotation. Volumes = "io.kubernetes.cri-o.Volumes" - // HostNetwork indicates whether the host network namespace is used or not + // HostNetwork indicates whether the host network namespace is used or not. HostNetwork = "io.kubernetes.cri-o.HostNetwork" - // CNIResult is the JSON string representation of the Result from CNI + // CNIResult is the JSON string representation of the Result from CNI. CNIResult = "io.kubernetes.cri-o.CNIResult" // ContainerManager is the annotation key for indicating the creator and - // manager of the container + // manager of the container. ContainerManager = "io.container.manager" ) // ContainerType values const ( - // ContainerTypeSandbox represents a pod sandbox container + // ContainerTypeSandbox represents a pod sandbox container. ContainerTypeSandbox = "sandbox" - // ContainerTypeContainer represents a container running within a pod + // ContainerTypeContainer represents a container running within a pod. ContainerTypeContainer = "container" ) // ContainerManagerLibpod indicates that libpod created and manages the -// container +// container. const ContainerManagerLibpod = "libpod" diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go index 99f14d02f..77b16b03e 100644 --- a/pkg/api/handlers/compat/containers_stats.go +++ b/pkg/api/handlers/compat/containers_stats.go @@ -56,7 +56,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { return } - stats, err := ctnr.GetContainerStats(&define.ContainerStats{}) + stats, err := ctnr.GetContainerStats(nil) if err != nil { utils.InternalServerError(w, errors.Wrapf(err, "failed to obtain Container %s stats", name)) return diff --git a/pkg/api/handlers/compat/images_prune.go b/pkg/api/handlers/compat/images_prune.go index 88776dc49..c0be9da7d 100644 --- a/pkg/api/handlers/compat/images_prune.go +++ b/pkg/api/handlers/compat/images_prune.go @@ -43,7 +43,7 @@ func PruneImages(w http.ResponseWriter, r *http.Request) { return } - idr := make([]types.ImageDeleteResponseItem, len(imagePruneReports)) + idr := make([]types.ImageDeleteResponseItem, 0, len(imagePruneReports)) var reclaimedSpace uint64 var errorMsg bytes.Buffer for _, p := range imagePruneReports { diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go index eb1a5d59c..89d914e0a 100644 --- a/pkg/api/handlers/compat/networks.go +++ b/pkg/api/handlers/compat/networks.go @@ -242,7 +242,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) { body := struct { ID string `json:"Id"` - Warning []string + Warning string }{ ID: newNetwork.ID, } diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index eb9fb12a6..cddf4c205 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -367,10 +367,13 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder) query := struct { - Changes []string `schema:"changes"` - Message string `schema:"message"` - Reference string `schema:"reference"` - URL string `schema:"URL"` + Changes []string `schema:"changes"` + Message string `schema:"message"` + Reference string `schema:"reference"` + URL string `schema:"URL"` + OS string `schema:"OS"` + Architecture string `schema:"Architecture"` + Variant string `schema:"Variant"` }{ // Add defaults here once needed. } @@ -402,10 +405,13 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) { imageEngine := abi.ImageEngine{Libpod: runtime} importOptions := entities.ImageImportOptions{ - Changes: query.Changes, - Message: query.Message, - Reference: query.Reference, - Source: source, + Changes: query.Changes, + Message: query.Message, + Reference: query.Reference, + OS: query.OS, + Architecture: query.Architecture, + Variant: query.Variant, + Source: source, } report, err := imageEngine.Import(r.Context(), importOptions) if err != nil { @@ -613,6 +619,7 @@ func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) { query := struct { All bool `schema:"all"` Force bool `schema:"force"` + Ignore bool `schema:"ignore"` Images []string `schema:"images"` }{} @@ -621,7 +628,7 @@ func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) { return } - opts := entities.ImageRemoveOptions{All: query.All, Force: query.Force} + opts := entities.ImageRemoveOptions{All: query.All, Force: query.Force, Ignore: query.Ignore} imageEngine := abi.ImageEngine{Libpod: runtime} rmReport, rmErrors := imageEngine.Remove(r.Context(), query.Images, opts) strErrs := errorhandling.ErrorsToStrings(rmErrors) diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go index 250736579..ad662f32c 100644 --- a/pkg/api/handlers/libpod/manifests.go +++ b/pkg/api/handlers/libpod/manifests.go @@ -401,7 +401,7 @@ func ManifestModify(w http.ResponseWriter, r *http.Request) { case len(report.Errors) > 0 && len(report.Images) > 0: statusCode = http.StatusConflict case len(report.Errors) > 0: - statusCode = http.StatusInternalServerError + statusCode = http.StatusBadRequest } utils.WriteResponse(w, statusCode, report) } diff --git a/pkg/api/handlers/libpod/play.go b/pkg/api/handlers/libpod/play.go index aed889298..ca9ada761 100644 --- a/pkg/api/handlers/libpod/play.go +++ b/pkg/api/handlers/libpod/play.go @@ -1,11 +1,8 @@ package libpod import ( - "io" - "io/ioutil" "net" "net/http" - "os" "github.com/containers/image/v5/types" "github.com/containers/podman/v4/libpod" @@ -16,7 +13,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/gorilla/schema" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) func PlayKube(w http.ResponseWriter, r *http.Request) { @@ -62,28 +58,6 @@ func PlayKube(w http.ResponseWriter, r *http.Request) { staticMACs = append(staticMACs, mac) } - // Fetch the K8s YAML file from the body, and copy it to a temp file. - tmpfile, err := ioutil.TempFile("", "libpod-play-kube.yml") - if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) - return - } - defer func() { - if err := os.Remove(tmpfile.Name()); err != nil { - logrus.Warn(err) - } - }() - if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF { - if err := tmpfile.Close(); err != nil { - logrus.Warn(err) - } - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file")) - return - } - if err := tmpfile.Close(); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error closing temporary file")) - return - } authConf, authfile, err := auth.GetCredentials(r) if err != nil { utils.Error(w, http.StatusBadRequest, err) @@ -116,7 +90,8 @@ func PlayKube(w http.ResponseWriter, r *http.Request) { if _, found := r.URL.Query()["start"]; found { options.Start = types.NewOptionalBool(query.Start) } - report, err := containerEngine.PlayKube(r.Context(), tmpfile.Name(), options) + report, err := containerEngine.PlayKube(r.Context(), r.Body, options) + _ = r.Body.Close() if err != nil { utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error playing YAML file")) return @@ -126,30 +101,10 @@ func PlayKube(w http.ResponseWriter, r *http.Request) { func PlayKubeDown(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) - tmpfile, err := ioutil.TempFile("", "libpod-play-kube.yml") - if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) - return - } - defer func() { - if err := os.Remove(tmpfile.Name()); err != nil { - logrus.Warn(err) - } - }() - if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF { - if err := tmpfile.Close(); err != nil { - logrus.Warn(err) - } - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file")) - return - } - if err := tmpfile.Close(); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error closing temporary file")) - return - } containerEngine := abi.ContainerEngine{Libpod: runtime} options := new(entities.PlayKubeDownOptions) - report, err := containerEngine.PlayKubeDown(r.Context(), tmpfile.Name(), *options) + report, err := containerEngine.PlayKubeDown(r.Context(), r.Body, *options) + _ = r.Body.Close() if err != nil { utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error tearing down YAML file")) return diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go index 15b16bc43..7154f5616 100644 --- a/pkg/api/handlers/utils/images.go +++ b/pkg/api/handlers/utils/images.go @@ -63,7 +63,7 @@ func IsRegistryReference(name string) error { imageRef, err := alltransports.ParseImageName(name) if err != nil { // No supported transport -> assume a docker-stype reference. - return nil + return nil // nolint: nilerr } if imageRef.Transport().Name() == docker.Transport.Name() { return nil diff --git a/pkg/api/server/register_exec.go b/pkg/api/server/register_exec.go index c19ca7859..90136463d 100644 --- a/pkg/api/server/register_exec.go +++ b/pkg/api/server/register_exec.go @@ -169,7 +169,7 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error { // - application/json // responses: // 200: - // description: no error + // $ref: "#/responses/InspectExecSession" // 404: // $ref: "#/responses/NoSuchExecInstance" // 500: diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 017310f12..89f808e7d 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -944,6 +944,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // name: force // description: Force image removal (including containers using the images). // type: boolean + // - in: query + // name: ignore + // description: Ignore if a specified image does not exist and do not throw an error. + // type: boolean // produces: // - application/json // responses: diff --git a/pkg/api/server/register_networks.go b/pkg/api/server/register_networks.go index 4466c938f..b900aa953 100644 --- a/pkg/api/server/register_networks.go +++ b/pkg/api/server/register_networks.go @@ -105,8 +105,15 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error { // schema: // $ref: "#/definitions/NetworkCreateRequest" // responses: - // 200: - // $ref: "#/responses/CompatNetworkCreate" + // 201: + // description: network created + // schema: + // type: object + // properties: + // Id: + // type: string + // Warning: + // type: string // 400: // $ref: "#/responses/BadParamError" // 500: diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go index 9b652be87..6cf89581a 100644 --- a/pkg/api/server/swagger.go +++ b/pkg/api/server/swagger.go @@ -235,3 +235,12 @@ type swagSystemAuthResponse struct { entities.AuthReport } } + +// Inspect response +// swagger:response InspectExecSession +type swagInspectExecSession struct { + // in:body + Body struct { + define.InspectExecSession + } +} diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go index f410606e4..0c6ebdd2f 100644 --- a/pkg/bindings/containers/attach.go +++ b/pkg/bindings/containers/attach.go @@ -279,7 +279,7 @@ func DemuxFrame(r io.Reader, buffer []byte, length int) (frame []byte, err error n, err := io.ReadFull(r, buffer[0:length]) if err != nil { - return nil, nil + return nil, err } if n < length { err = io.ErrUnexpectedEOF diff --git a/pkg/bindings/generator/generator.go b/pkg/bindings/generator/generator.go index a224013ea..e69973be1 100644 --- a/pkg/bindings/generator/generator.go +++ b/pkg/bindings/generator/generator.go @@ -1,3 +1,4 @@ +//go:build ignore // +build ignore package main diff --git a/pkg/bindings/images/build_unix.go b/pkg/bindings/images/build_unix.go index 0afb1deb6..67a5e2998 100644 --- a/pkg/bindings/images/build_unix.go +++ b/pkg/bindings/images/build_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package images diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go index a44a3527f..75cb38a0a 100644 --- a/pkg/bindings/images/types.go +++ b/pkg/bindings/images/types.go @@ -11,6 +11,8 @@ type RemoveOptions struct { All *bool // Forces removes all containers based on the image Force *bool + // Ignore if a specified image does not exist and do not throw an error. + Ignore *bool } //go:generate go run ../generator/generator.go DiffOptions @@ -101,6 +103,12 @@ type ImportOptions struct { Reference *string // Url to option image to import. Cannot be used with the reader URL *string + // OS for the imported image + OS *string + // Architecture for the imported image + Architecture *string + // Variant for the imported image + Variant *string } //go:generate go run ../generator/generator.go PushOptions diff --git a/pkg/bindings/images/types_import_options.go b/pkg/bindings/images/types_import_options.go index ea66fa312..f958fe8b4 100644 --- a/pkg/bindings/images/types_import_options.go +++ b/pkg/bindings/images/types_import_options.go @@ -76,3 +76,48 @@ func (o *ImportOptions) GetURL() string { } return *o.URL } + +// WithOS set field OS to given value +func (o *ImportOptions) WithOS(value string) *ImportOptions { + o.OS = &value + return o +} + +// GetOS returns value of field OS +func (o *ImportOptions) GetOS() string { + if o.OS == nil { + var z string + return z + } + return *o.OS +} + +// WithArchitecture set field Architecture to given value +func (o *ImportOptions) WithArchitecture(value string) *ImportOptions { + o.Architecture = &value + return o +} + +// GetArchitecture returns value of field Architecture +func (o *ImportOptions) GetArchitecture() string { + if o.Architecture == nil { + var z string + return z + } + return *o.Architecture +} + +// WithVariant set field Variant to given value +func (o *ImportOptions) WithVariant(value string) *ImportOptions { + o.Variant = &value + return o +} + +// GetVariant returns value of field Variant +func (o *ImportOptions) GetVariant() string { + if o.Variant == nil { + var z string + return z + } + return *o.Variant +} diff --git a/pkg/bindings/images/types_remove_options.go b/pkg/bindings/images/types_remove_options.go index 1fbe5f4ea..613a33183 100644 --- a/pkg/bindings/images/types_remove_options.go +++ b/pkg/bindings/images/types_remove_options.go @@ -46,3 +46,18 @@ func (o *RemoveOptions) GetForce() bool { } return *o.Force } + +// WithIgnore set field Ignore to given value +func (o *RemoveOptions) WithIgnore(value bool) *RemoveOptions { + o.Ignore = &value + return o +} + +// GetIgnore returns value of field Ignore +func (o *RemoveOptions) GetIgnore() bool { + if o.Ignore == nil { + var z bool + return z + } + return *o.Ignore +} diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go index 458cb913a..f7cd0d262 100644 --- a/pkg/bindings/manifests/manifests.go +++ b/pkg/bindings/manifests/manifests.go @@ -2,10 +2,9 @@ package manifests import ( "context" - "errors" "fmt" + "io/ioutil" "net/http" - "net/url" "strconv" "strings" @@ -14,8 +13,11 @@ import ( "github.com/containers/podman/v4/pkg/api/handlers" "github.com/containers/podman/v4/pkg/bindings" "github.com/containers/podman/v4/pkg/bindings/images" + "github.com/containers/podman/v4/pkg/domain/entities" + "github.com/containers/podman/v4/pkg/errorhandling" "github.com/containers/podman/v4/version" jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" ) // Create creates a manifest for the given name. Optional images to be associated with @@ -135,30 +137,8 @@ func Add(ctx context.Context, name string, options *AddOptions) (string, error) // Remove deletes a manifest entry from a manifest list. Both name and the digest to be // removed are mandatory inputs. The ID of the new manifest list is returned as a string. func Remove(ctx context.Context, name, digest string, _ *RemoveOptions) (string, error) { - if bindings.ServiceVersion(ctx).GTE(semver.MustParse("4.0.0")) { - optionsv4 := new(ModifyOptions).WithOperation("remove") - return Modify(ctx, name, []string{digest}, optionsv4) - } - - // API Version < 4.0.0 - conn, err := bindings.GetClient(ctx) - if err != nil { - return "", err - } - - headers := http.Header{} - headers.Add("API-Version", "3.4.0") - - params := url.Values{} - params.Set("digest", digest) - response, err := conn.DoRequest(ctx, nil, http.MethodDelete, "/manifests/%s", params, headers, name) - if err != nil { - return "", err - } - defer response.Body.Close() - - var idr handlers.IDResponse - return idr.ID, response.Process(&idr) + optionsv4 := new(ModifyOptions).WithOperation("remove") + return Modify(ctx, name, []string{digest}, optionsv4) } // Push takes a manifest list and pushes to a destination. If the destination is not specified, @@ -229,8 +209,36 @@ func Modify(ctx context.Context, name string, images []string, options *ModifyOp } defer response.Body.Close() - var idr handlers.IDResponse - return idr.ID, response.Process(&idr) + data, err := ioutil.ReadAll(response.Body) + if err != nil { + return "", errors.Wrap(err, "unable to process API response") + } + + if response.IsSuccess() || response.IsRedirection() { + var report entities.ManifestModifyReport + if err = jsoniter.Unmarshal(data, &report); err != nil { + return "", errors.Wrap(err, "unable to decode API response") + } + + err = errorhandling.JoinErrors(report.Errors) + if err != nil { + errModel := errorhandling.ErrorModel{ + Because: (errors.Cause(err)).Error(), + Message: err.Error(), + ResponseCode: response.StatusCode, + } + return report.ID, &errModel + } + return report.ID, nil + } + + errModel := errorhandling.ErrorModel{ + ResponseCode: response.StatusCode, + } + if err = jsoniter.Unmarshal(data, &errModel); err != nil { + return "", errors.Wrap(err, "unable to decode API response") + } + return "", &errModel } // Annotate modifies the given manifest list using options and the optional list of images diff --git a/pkg/bindings/play/play.go b/pkg/bindings/play/play.go index d4018b6b3..8058a8514 100644 --- a/pkg/bindings/play/play.go +++ b/pkg/bindings/play/play.go @@ -2,6 +2,7 @@ package play import ( "context" + "io" "net/http" "os" "strconv" @@ -14,20 +15,25 @@ import ( ) func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.PlayKubeReport, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + + return KubeWithBody(ctx, f, options) +} + +func KubeWithBody(ctx context.Context, body io.Reader, options *KubeOptions) (*entities.PlayKubeReport, error) { var report entities.PlayKubeReport if options == nil { options = new(KubeOptions) } - conn, err := bindings.GetClient(ctx) - if err != nil { - return nil, err - } - f, err := os.Open(path) + conn, err := bindings.GetClient(ctx) if err != nil { return nil, err } - defer f.Close() params, err := options.ToParams() if err != nil { @@ -46,7 +52,7 @@ func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.Pla return nil, err } - response, err := conn.DoRequest(ctx, f, http.MethodPost, "/play/kube", params, header) + response, err := conn.DoRequest(ctx, body, http.MethodPost, "/play/kube", params, header) if err != nil { return nil, err } @@ -60,12 +66,6 @@ func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.Pla } func KubeDown(ctx context.Context, path string) (*entities.PlayKubeReport, error) { - var report entities.PlayKubeReport - conn, err := bindings.GetClient(ctx) - if err != nil { - return nil, err - } - f, err := os.Open(path) if err != nil { return nil, err @@ -75,7 +75,18 @@ func KubeDown(ctx context.Context, path string) (*entities.PlayKubeReport, error logrus.Warn(err) } }() - response, err := conn.DoRequest(ctx, f, http.MethodDelete, "/play/kube", nil, nil) + + return KubeDownWithBody(ctx, f) +} + +func KubeDownWithBody(ctx context.Context, body io.Reader) (*entities.PlayKubeReport, error) { + var report entities.PlayKubeReport + conn, err := bindings.GetClient(ctx) + if err != nil { + return nil, err + } + + response, err := conn.DoRequest(ctx, body, http.MethodDelete, "/play/kube", nil, nil) if err != nil { return nil, err } diff --git a/pkg/bindings/test/attach_test.go b/pkg/bindings/test/attach_test.go index 670566882..dcebe0809 100644 --- a/pkg/bindings/test/attach_test.go +++ b/pkg/bindings/test/attach_test.go @@ -44,7 +44,8 @@ var _ = Describe("Podman containers attach", func() { timeout := uint(5) err := containers.Stop(bt.conn, id, new(containers.StopOptions).WithTimeout(timeout)) if err != nil { - GinkgoWriter.Write([]byte(err.Error())) + _, writeErr := GinkgoWriter.Write([]byte(err.Error())) + Expect(writeErr).ShouldNot(HaveOccurred()) } }() diff --git a/pkg/bindings/test/auth_test.go b/pkg/bindings/test/auth_test.go index b421f0797..c4c4b16d8 100644 --- a/pkg/bindings/test/auth_test.go +++ b/pkg/bindings/test/auth_test.go @@ -40,7 +40,8 @@ var _ = Describe("Podman images", func() { AfterEach(func() { s.Kill() bt.cleanup() - registry.Stop() + err := registry.Stop() + Expect(err).To(BeNil()) }) // Test using credentials. diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go index f51e5f404..f2602967b 100644 --- a/pkg/bindings/test/common_test.go +++ b/pkg/bindings/test/common_test.go @@ -211,7 +211,7 @@ func (b *bindingTest) RunTopContainer(containerName *string, podName *string) (s } ctr, err := containers.CreateWithSpec(b.conn, s, nil) if err != nil { - return "", nil + return "", err } err = containers.Start(b.conn, ctr.ID, nil) if err != nil { diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go index 9411d8a5f..bf627fdba 100644 --- a/pkg/bindings/test/containers_test.go +++ b/pkg/bindings/test/containers_test.go @@ -322,7 +322,8 @@ var _ = Describe("Podman containers ", func() { // a container that has no healthcheck should be a 409 var name = "top" - bt.RunTopContainer(&name, nil) + _, err = bt.RunTopContainer(&name, nil) + Expect(err).To(BeNil()) _, err = containers.RunHealthCheck(bt.conn, name, nil) Expect(err).ToNot(BeNil()) code, _ = bindings.CheckResponseCode(err) diff --git a/pkg/checkpoint/crutils/checkpoint_restore_utils.go b/pkg/checkpoint/crutils/checkpoint_restore_utils.go index 2765d18e8..6a8a7894a 100644 --- a/pkg/checkpoint/crutils/checkpoint_restore_utils.go +++ b/pkg/checkpoint/crutils/checkpoint_restore_utils.go @@ -99,13 +99,12 @@ func CRRemoveDeletedFiles(id, baseDirectory, containerRootDirectory string) erro // root file system changes on top of containerRootDirectory func CRApplyRootFsDiffTar(baseDirectory, containerRootDirectory string) error { rootfsDiffPath := filepath.Join(baseDirectory, metadata.RootFsDiffTar) - if _, err := os.Stat(rootfsDiffPath); err != nil { - // Only do this if a rootfs-diff.tar actually exists - return nil - } - + // Only do this if a rootfs-diff.tar actually exists rootfsDiffFile, err := os.Open(rootfsDiffPath) if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil + } return errors.Wrap(err, "failed to open root file-system diff file") } defer rootfsDiffFile.Close() diff --git a/pkg/criu/criu.go b/pkg/criu/criu.go index 967da0dca..b54870abc 100644 --- a/pkg/criu/criu.go +++ b/pkg/criu/criu.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package criu diff --git a/pkg/criu/criu_unsupported.go b/pkg/criu/criu_unsupported.go index 51cd0c1fd..3e3ed9c6c 100644 --- a/pkg/criu/criu_unsupported.go +++ b/pkg/criu/criu_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package criu diff --git a/pkg/ctime/ctime_linux.go b/pkg/ctime/ctime_linux.go index 113693e87..7eb3caa6d 100644 --- a/pkg/ctime/ctime_linux.go +++ b/pkg/ctime/ctime_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package ctime diff --git a/pkg/ctime/ctime_unsupported.go b/pkg/ctime/ctime_unsupported.go index 325731353..afee56027 100644 --- a/pkg/ctime/ctime_unsupported.go +++ b/pkg/ctime/ctime_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package ctime diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go index 7cf7ca17f..6b70a3452 100644 --- a/pkg/domain/entities/engine_container.go +++ b/pkg/domain/entities/engine_container.go @@ -68,8 +68,8 @@ type ContainerEngine interface { NetworkPrune(ctx context.Context, options NetworkPruneOptions) ([]*NetworkPruneReport, error) NetworkReload(ctx context.Context, names []string, options NetworkReloadOptions) ([]*NetworkReloadReport, error) NetworkRm(ctx context.Context, namesOrIds []string, options NetworkRmOptions) ([]*NetworkRmReport, error) - PlayKube(ctx context.Context, path string, opts PlayKubeOptions) (*PlayKubeReport, error) - PlayKubeDown(ctx context.Context, path string, opts PlayKubeDownOptions) (*PlayKubeReport, error) + PlayKube(ctx context.Context, body io.Reader, opts PlayKubeOptions) (*PlayKubeReport, error) + PlayKubeDown(ctx context.Context, body io.Reader, opts PlayKubeDownOptions) (*PlayKubeReport, error) PodCreate(ctx context.Context, specg PodSpec) (*PodCreateReport, error) PodExists(ctx context.Context, nameOrID string) (*BoolReport, error) PodInspect(ctx context.Context, options PodInspectOptions) (*PodInspectReport, error) diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index 2ac21cfeb..7081c5d25 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -90,6 +90,8 @@ type ImageRemoveOptions struct { All bool // Foce will force image removal including containers using the images. Force bool + // Ignore if a specified image does not exist and do not throw an error. + Ignore bool // Confirms if given name is a manifest list and removes it, otherwise returns error. LookupManifest bool } @@ -277,6 +279,7 @@ type ImageLoadReport struct { type ImageImportOptions struct { Architecture string + Variant string Changes []string Message string OS string diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go index 4d9ced900..bed3183e9 100644 --- a/pkg/domain/entities/types.go +++ b/pkg/domain/entities/types.go @@ -20,7 +20,7 @@ type Volume struct { } type Report struct { - Id []string //nolint + Id []string // nolint Err map[string]error } @@ -98,8 +98,10 @@ type EventsOptions struct { // ContainerCreateResponse is the response struct for creating a container type ContainerCreateResponse struct { // ID of the container created + // required: true ID string `json:"Id"` // Warnings during container creation + // required: true Warnings []string `json:"Warnings"` } diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go index 85ba4f84f..4c6964a00 100644 --- a/pkg/domain/filters/containers.go +++ b/pkg/domain/filters/containers.go @@ -213,8 +213,10 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo for _, val := range filterValues { net, err := r.Network().NetworkInspect(val) if err != nil { - // ignore not found errors - break + if errors.Is(err, define.ErrNoSuchNetwork) { + continue + } + return nil, err } inputNetNames = append(inputNetNames, net.Name) } diff --git a/pkg/domain/filters/pods.go b/pkg/domain/filters/pods.go index 2f9442dff..e22480006 100644 --- a/pkg/domain/filters/pods.go +++ b/pkg/domain/filters/pods.go @@ -131,8 +131,10 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti for _, val := range filterValues { net, err := r.Network().NetworkInspect(val) if err != nil { - // ignore not found errors - break + if errors.Is(err, define.ErrNoSuchNetwork) { + continue + } + return nil, err } inputNetNames = append(inputNetNames, net.Name) } diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index e6feb7c82..f45bdeba5 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -1431,12 +1431,7 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri reportStats := []define.ContainerStats{} for _, ctr := range containers { - prev, ok := containerStats[ctr.ID()] - if !ok { - prev = &define.ContainerStats{} - } - - stats, err := ctr.GetContainerStats(prev) + stats, err := ctr.GetContainerStats(containerStats[ctr.ID()]) if err != nil { cause := errors.Cause(err) if queryAll && (cause == define.ErrCtrRemoved || cause == define.ErrNoSuchCtr || cause == define.ErrCtrStateInvalid) { @@ -1501,6 +1496,35 @@ func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts enti return nil, err } + if ctrCloneOpts.CreateOpts.Pod != "" { + pod, err := ic.Libpod.LookupPod(ctrCloneOpts.CreateOpts.Pod) + if err != nil { + return nil, err + } + + allNamespaces := []struct { + isShared bool + value *specgen.Namespace + }{ + {pod.SharesPID(), &spec.PidNS}, + {pod.SharesNet(), &spec.NetNS}, + {pod.SharesCgroup(), &spec.CgroupNS}, + {pod.SharesIPC(), &spec.IpcNS}, + {pod.SharesUTS(), &spec.UtsNS}, + } + + printWarning := false + for _, n := range allNamespaces { + if n.isShared && !n.value.IsDefault() { + *n.value = specgen.Namespace{NSMode: specgen.Default} + printWarning = true + } + } + if printWarning { + logrus.Warning("At least one namespace was reset to the default configuration") + } + } + err = specgenutil.FillOutSpecGen(spec, &ctrCloneOpts.CreateOpts, []string{}) if err != nil { return nil, err diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 0b1281aac..74478b26d 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -445,7 +445,8 @@ func (ir *ImageEngine) Import(ctx context.Context, options entities.ImageImportO importOptions.Tag = options.Reference importOptions.SignaturePolicyPath = options.SignaturePolicy importOptions.OS = options.OS - importOptions.Architecture = options.Architecture + importOptions.Arch = options.Architecture + importOptions.Variant = options.Variant if !options.Quiet { importOptions.Writer = os.Stderr @@ -578,6 +579,7 @@ func (ir *ImageEngine) Remove(ctx context.Context, images []string, opts entitie libimageOptions := &libimage.RemoveImagesOptions{} libimageOptions.Filters = []string{"readonly=false"} libimageOptions.Force = opts.Force + libimageOptions.Ignore = opts.Ignore libimageOptions.LookupManifest = opts.LookupManifest if !opts.All { libimageOptions.Filters = append(libimageOptions.Filters, "intermediate=false") @@ -847,13 +849,12 @@ func execPodman(execUser *user.User, command []string) error { if err != nil { return err } - defer func() error { - err := cmdLogin.Process.Kill() - if err != nil { - return err - } - return cmdLogin.Wait() + + defer func() { + _ = cmdLogin.Process.Kill() + _ = cmdLogin.Wait() }() + cmd := exec.Command(command[0], command[1:]...) cmd.Env = []string{"PATH=" + os.Getenv("PATH"), "TERM=" + os.Getenv("TERM")} cmd.Stderr = os.Stderr diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index 4d8c5a381..1423ab06e 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -33,12 +33,12 @@ import ( yamlv2 "gopkg.in/yaml.v2" ) -func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) { +func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) { report := &entities.PlayKubeReport{} validKinds := 0 // read yaml document - content, err := ioutil.ReadFile(path) + content, err := ioutil.ReadAll(body) if err != nil { return nil, err } @@ -52,7 +52,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en // sort kube kinds documentList, err = sortKubeKinds(documentList) if err != nil { - return nil, errors.Wrapf(err, "unable to sort kube kinds in %q", path) + return nil, errors.Wrap(err, "unable to sort kube kinds") } ipIndex := 0 @@ -64,7 +64,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en for _, document := range documentList { kind, err := getKubeKind(document) if err != nil { - return nil, errors.Wrapf(err, "unable to read %q as kube YAML", path) + return nil, errors.Wrap(err, "unable to read kube YAML") } switch kind { @@ -73,7 +73,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en var podTemplateSpec v1.PodTemplateSpec if err := yaml.Unmarshal(document, &podYAML); err != nil { - return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Pod", path) + return nil, errors.Wrap(err, "unable to read YAML as Kube Pod") } podTemplateSpec.ObjectMeta = podYAML.ObjectMeta @@ -97,7 +97,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en var deploymentYAML v1apps.Deployment if err := yaml.Unmarshal(document, &deploymentYAML); err != nil { - return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Deployment", path) + return nil, errors.Wrap(err, "unable to read YAML as Kube Deployment") } r, err := ic.playKubeDeployment(ctx, &deploymentYAML, options, &ipIndex, configMaps) @@ -111,7 +111,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en var pvcYAML v1.PersistentVolumeClaim if err := yaml.Unmarshal(document, &pvcYAML); err != nil { - return nil, errors.Wrapf(err, "unable to read YAML %q as Kube PersistentVolumeClaim", path) + return nil, errors.Wrap(err, "unable to read YAML as Kube PersistentVolumeClaim") } r, err := ic.playKubePVC(ctx, &pvcYAML, options) @@ -125,7 +125,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en var configMap v1.ConfigMap if err := yaml.Unmarshal(document, &configMap); err != nil { - return nil, errors.Wrapf(err, "unable to read YAML %q as Kube ConfigMap", path) + return nil, errors.Wrap(err, "unable to read YAML as Kube ConfigMap") } configMaps = append(configMaps, configMap) default: @@ -215,7 +215,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY // FIXME This is very hard to support properly with a good ux if len(options.StaticIPs) > *ipIndex { if !podOpt.Net.Network.IsBridge() { - errors.Wrap(define.ErrInvalidArg, "static ip addresses can only be set when the network mode is bridge") + return nil, errors.Wrap(define.ErrInvalidArg, "static ip addresses can only be set when the network mode is bridge") } if len(podOpt.Net.Networks) != 1 { return nil, errors.Wrap(define.ErrInvalidArg, "cannot set static ip addresses for more than network, use netname:ip=<ip> syntax to specify ips for more than network") @@ -230,7 +230,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY } if len(options.StaticMACs) > *ipIndex { if !podOpt.Net.Network.IsBridge() { - errors.Wrap(define.ErrInvalidArg, "static mac address can only be set when the network mode is bridge") + return nil, errors.Wrap(define.ErrInvalidArg, "static mac address can only be set when the network mode is bridge") } if len(podOpt.Net.Networks) != 1 { return nil, errors.Wrap(define.ErrInvalidArg, "cannot set static mac address for more than network, use netname:mac=<mac> syntax to specify mac for more than network") @@ -773,14 +773,14 @@ func getBuildFile(imageName string, cwd string) (string, error) { return "", err } -func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, path string, _ entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) { +func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, body io.Reader, _ entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) { var ( podNames []string ) reports := new(entities.PlayKubeReport) // read yaml document - content, err := ioutil.ReadFile(path) + content, err := ioutil.ReadAll(body) if err != nil { return nil, err } @@ -794,27 +794,27 @@ func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, path string, _ enti // sort kube kinds documentList, err = sortKubeKinds(documentList) if err != nil { - return nil, errors.Wrapf(err, "unable to sort kube kinds in %q", path) + return nil, errors.Wrap(err, "unable to sort kube kinds") } for _, document := range documentList { kind, err := getKubeKind(document) if err != nil { - return nil, errors.Wrapf(err, "unable to read %q as kube YAML", path) + return nil, errors.Wrap(err, "unable to read as kube YAML") } switch kind { case "Pod": var podYAML v1.Pod if err := yaml.Unmarshal(document, &podYAML); err != nil { - return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Pod", path) + return nil, errors.Wrap(err, "unable to read YAML as Kube Pod") } podNames = append(podNames, podYAML.ObjectMeta.Name) case "Deployment": var deploymentYAML v1apps.Deployment if err := yaml.Unmarshal(document, &deploymentYAML); err != nil { - return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Deployment", path) + return nil, errors.Wrap(err, "unable to read YAML as Kube Deployment") } var numReplicas int32 = 1 deploymentName := deploymentYAML.ObjectMeta.Name diff --git a/pkg/domain/infra/abi/terminal/sigproxy_linux.go b/pkg/domain/infra/abi/terminal/sigproxy_linux.go index 206ded091..fe2c268c0 100644 --- a/pkg/domain/infra/abi/terminal/sigproxy_linux.go +++ b/pkg/domain/infra/abi/terminal/sigproxy_linux.go @@ -20,7 +20,7 @@ const signalBufferSize = 2048 func ProxySignals(ctr *libpod.Container) { // Stop catching the shutdown signals (SIGINT, SIGTERM) - they're going // to the container now. - shutdown.Stop() + shutdown.Stop() // nolint: errcheck sigBuffer := make(chan os.Signal, signalBufferSize) signal.CatchAll(sigBuffer) diff --git a/pkg/domain/infra/abi/terminal/terminal_linux.go b/pkg/domain/infra/abi/terminal/terminal_linux.go index 78c792d2b..153b19fdb 100644 --- a/pkg/domain/infra/abi/terminal/terminal_linux.go +++ b/pkg/domain/infra/abi/terminal/terminal_linux.go @@ -39,7 +39,7 @@ func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpo // 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 +func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool) error { //nolint: interfacer resize := make(chan define.TerminalSize) haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd())) diff --git a/pkg/domain/infra/abi/volumes.go b/pkg/domain/infra/abi/volumes.go index 19fc6d2d3..f59f11e20 100644 --- a/pkg/domain/infra/abi/volumes.go +++ b/pkg/domain/infra/abi/volumes.go @@ -171,7 +171,8 @@ func (ic *ContainerEngine) VolumeMounted(ctx context.Context, nameOrID string) ( } mountCount, err := vol.MountCount() if err != nil { - return &entities.BoolReport{Value: false}, nil + // FIXME: this error should probably be returned + return &entities.BoolReport{Value: false}, nil // nolint: nilerr } if mountCount > 0 { return &entities.BoolReport{Value: true}, nil diff --git a/pkg/domain/infra/runtime_abi.go b/pkg/domain/infra/runtime_abi.go index 5b7b7cf8a..39989c96b 100644 --- a/pkg/domain/infra/runtime_abi.go +++ b/pkg/domain/infra/runtime_abi.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package infra diff --git a/pkg/domain/infra/runtime_abi_unsupported.go b/pkg/domain/infra/runtime_abi_unsupported.go index b4414dc54..9e5bd01eb 100644 --- a/pkg/domain/infra/runtime_abi_unsupported.go +++ b/pkg/domain/infra/runtime_abi_unsupported.go @@ -1,3 +1,4 @@ +//go:build remote // +build remote package infra diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go index f9ceb9305..dffd90dbe 100644 --- a/pkg/domain/infra/runtime_libpod.go +++ b/pkg/domain/infra/runtime_libpod.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package infra diff --git a/pkg/domain/infra/runtime_proxy.go b/pkg/domain/infra/runtime_proxy.go index a70b61165..e5761d4ab 100644 --- a/pkg/domain/infra/runtime_proxy.go +++ b/pkg/domain/infra/runtime_proxy.go @@ -1,3 +1,4 @@ +//go:build !remote // +build !remote package infra diff --git a/pkg/domain/infra/runtime_tunnel.go b/pkg/domain/infra/runtime_tunnel.go index 68f8b0dac..8a4de032f 100644 --- a/pkg/domain/infra/runtime_tunnel.go +++ b/pkg/domain/infra/runtime_tunnel.go @@ -1,3 +1,4 @@ +//go:build remote // +build remote package infra diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 046c2509d..10bfb3984 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -840,7 +840,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta if eventsErr != nil || lastEvent == nil { logrus.Errorf("Cannot get exit code: %v", err) report.ExitCode = define.ExecErrorCodeNotFound - return &report, nil // compat with local client + return &report, nil // nolint: nilerr } report.ExitCode = lastEvent.ContainerExitCode @@ -938,7 +938,7 @@ func (ic *ContainerEngine) ContainerStat(ctx context.Context, nameOrID string, p return containers.Stat(ic.ClientCtx, nameOrID, path) } -// Shutdown Libpod engine +// Shutdown Libpod engine. func (ic *ContainerEngine) Shutdown(_ context.Context) { } @@ -949,7 +949,7 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri return containers.Stats(ic.ClientCtx, namesOrIds, new(containers.StatsOptions).WithStream(options.Stream).WithInterval(options.Interval)) } -// ShouldRestart reports back whether the container will restart +// ShouldRestart reports back whether the container will restart. func (ic *ContainerEngine) ShouldRestart(_ context.Context, id string) (bool, error) { return containers.ShouldRestart(ic.ClientCtx, id, nil) } diff --git a/pkg/domain/infra/tunnel/events.go b/pkg/domain/infra/tunnel/events.go index 1f27cdff8..b472ad03a 100644 --- a/pkg/domain/infra/tunnel/events.go +++ b/pkg/domain/infra/tunnel/events.go @@ -34,7 +34,7 @@ func (ic *ContainerEngine) Events(ctx context.Context, opts entities.EventsOptio } // GetLastContainerEvent takes a container name or ID and an event status and returns -// the last occurrence of the container event +// the last occurrence of the container event. func (ic *ContainerEngine) GetLastContainerEvent(ctx context.Context, nameOrID string, containerEvent events.Status) (*events.Event, error) { // check to make sure the event.Status is valid if _, err := events.StringToStatus(containerEvent.String()); err != nil { diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index 3ee97d94c..18e10e8dd 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -28,7 +28,7 @@ func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.Boo } func (ir *ImageEngine) Remove(ctx context.Context, imagesArg []string, opts entities.ImageRemoveOptions) (*entities.ImageRemoveReport, []error) { - options := new(images.RemoveOptions).WithForce(opts.Force).WithAll(opts.All) + options := new(images.RemoveOptions).WithForce(opts.Force).WithIgnore(opts.Ignore).WithAll(opts.All) return images.Remove(ir.ClientCtx, imagesArg, options) } @@ -230,6 +230,7 @@ func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOpti f *os.File ) options := new(images.ImportOptions).WithChanges(opts.Changes).WithMessage(opts.Message).WithReference(opts.Reference) + options.WithOS(opts.OS).WithArchitecture(opts.Architecture).WithVariant(opts.Variant) if opts.SourceIsURL { options.WithURL(opts.Source) } else { diff --git a/pkg/domain/infra/tunnel/play.go b/pkg/domain/infra/tunnel/play.go index cd51262d0..d9637254a 100644 --- a/pkg/domain/infra/tunnel/play.go +++ b/pkg/domain/infra/tunnel/play.go @@ -2,13 +2,14 @@ package tunnel import ( "context" + "io" "github.com/containers/image/v5/types" "github.com/containers/podman/v4/pkg/bindings/play" "github.com/containers/podman/v4/pkg/domain/entities" ) -func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, opts entities.PlayKubeOptions) (*entities.PlayKubeReport, error) { +func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, opts entities.PlayKubeOptions) (*entities.PlayKubeReport, error) { options := new(play.KubeOptions).WithAuthfile(opts.Authfile).WithUsername(opts.Username).WithPassword(opts.Password) options.WithCertDir(opts.CertDir).WithQuiet(opts.Quiet).WithSignaturePolicy(opts.SignaturePolicy).WithConfigMaps(opts.ConfigMaps) options.WithLogDriver(opts.LogDriver).WithNetwork(opts.Networks).WithSeccompProfileRoot(opts.SeccompProfileRoot) @@ -26,9 +27,9 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, opts entit if start := opts.Start; start != types.OptionalBoolUndefined { options.WithStart(start == types.OptionalBoolTrue) } - return play.Kube(ic.ClientCtx, path, options) + return play.KubeWithBody(ic.ClientCtx, body, options) } -func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, path string, _ entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) { - return play.KubeDown(ic.ClientCtx, path) +func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, body io.Reader, _ entities.PlayKubeDownOptions) (*entities.PlayKubeReport, error) { + return play.KubeDownWithBody(ic.ClientCtx, body) } diff --git a/pkg/env/env.go b/pkg/env/env.go index ecd2d62a5..5989d0da5 100644 --- a/pkg/env/env.go +++ b/pkg/env/env.go @@ -26,7 +26,7 @@ func DefaultEnvVariables() map[string]string { // Slice transforms the specified map of environment variables into a // slice. If a value is non-empty, the key and value are joined with '='. func Slice(m map[string]string) []string { - env := make([]string, len(m)) + env := make([]string, 0, len(m)) for k, v := range m { var s string if len(v) > 0 { diff --git a/pkg/env/env_unix.go b/pkg/env/env_unix.go index 16061a700..690078f33 100644 --- a/pkg/env/env_unix.go +++ b/pkg/env/env_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package env diff --git a/pkg/errorhandling/errorhandling.go b/pkg/errorhandling/errorhandling.go index 04110b62a..e33c26032 100644 --- a/pkg/errorhandling/errorhandling.go +++ b/pkg/errorhandling/errorhandling.go @@ -28,7 +28,7 @@ func JoinErrors(errs []error) error { finalErr := multiE.ErrorOrNil() if finalErr == nil { - return finalErr + return nil } return errors.New(strings.TrimSpace(finalErr.Error())) } diff --git a/pkg/inspect/inspect.go b/pkg/inspect/inspect.go index cd26db6b0..767d86daf 100644 --- a/pkg/inspect/inspect.go +++ b/pkg/inspect/inspect.go @@ -9,7 +9,7 @@ import ( v1 "github.com/opencontainers/image-spec/specs-go/v1" ) -// ImageData holds the inspect information of an image +// ImageData holds the inspect information of an image. type ImageData struct { ID string `json:"Id"` Digest digest.Digest `json:"Digest"` @@ -36,13 +36,13 @@ type ImageData struct { HealthCheck *manifest.Schema2HealthConfig `json:"Healthcheck,omitempty"` } -// RootFS holds the root fs information of an image +// RootFS holds the root fs information of an image. type RootFS struct { Type string `json:"Type"` Layers []digest.Digest `json:"Layers"` } -// ImageResult is used for podman images for collection and output +// ImageResult is used for podman images for collection and output. type ImageResult struct { Tag string Repository string diff --git a/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go b/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go index fccddc3e0..352cc028f 100644 --- a/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go +++ b/pkg/k8s.io/apimachinery/pkg/api/resource/quantity.go @@ -579,9 +579,9 @@ func (q Quantity) MarshalJSON() ([]byte, error) { // if CanonicalizeBytes needed more space than our slice provided, we may need to allocate again so use // append result = result[:1] - result = append(result, number...) - result = append(result, suffix...) - result = append(result, '"') + result = append(result, number...) // nolint: makezero + result = append(result, suffix...) // nolint: makezero + result = append(result, '"') // nolint: makezero return result, nil } diff --git a/pkg/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go b/pkg/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go index 2501d5516..a502b5adb 100644 --- a/pkg/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go +++ b/pkg/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go @@ -1,3 +1,4 @@ +//go:build !notest // +build !notest /* diff --git a/pkg/lookup/lookup.go b/pkg/lookup/lookup.go index 0b22a1974..0601e829d 100644 --- a/pkg/lookup/lookup.go +++ b/pkg/lookup/lookup.go @@ -14,7 +14,7 @@ const ( etcgroup = "/etc/group" ) -// Overrides allows you to override defaults in GetUserGroupInfo +// Overrides allows you to override defaults in GetUserGroupInfo. type Overrides struct { DefaultUser *user.ExecUser ContainerEtcPasswdPath string diff --git a/pkg/machine/config.go b/pkg/machine/config.go index b3b105150..aaf8da872 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -36,9 +36,9 @@ type InitOptions struct { type QemuMachineStatus = string const ( - // Running indicates the qemu vm is running + // Running indicates the qemu vm is running. Running QemuMachineStatus = "running" - // Stopped indicates the vm has stopped + // Stopped indicates the vm has stopped. Stopped QemuMachineStatus = "stopped" DefaultMachineName string = "podman-machine-default" ) @@ -147,7 +147,7 @@ func (rc RemoteConnectionType) MakeSSHURL(host, path, port, userName string) url } // GetDataDir returns the filepath where vm images should -// live for podman-machine +// live for podman-machine. func GetDataDir(vmType string) (string, error) { data, err := homedir.GetDataHome() if err != nil { diff --git a/pkg/machine/fcos.go b/pkg/machine/fcos.go index 4d3e2edf4..6215ae08f 100644 --- a/pkg/machine/fcos.go +++ b/pkg/machine/fcos.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine diff --git a/pkg/machine/fedora.go b/pkg/machine/fedora.go index cd713dde7..bed45c6da 100644 --- a/pkg/machine/fedora.go +++ b/pkg/machine/fedora.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine @@ -58,7 +59,10 @@ func (f FedoraDownload) Get() *Download { func (f FedoraDownload) HasUsableCache() (bool, error) { info, err := os.Stat(f.LocalPath) if err != nil { - return false, nil + if errors.Is(err, os.ErrNotExist) { + return false, nil + } + return false, err } return info.Size() == f.Size, nil } diff --git a/pkg/machine/ignition_darwin.go b/pkg/machine/ignition_darwin.go index 9ede4b026..b9fbf218d 100644 --- a/pkg/machine/ignition_darwin.go +++ b/pkg/machine/ignition_darwin.go @@ -1,4 +1,5 @@ -//+build darwin +//go:build darwin +// +build darwin package machine diff --git a/pkg/machine/ignition_schema.go b/pkg/machine/ignition_schema.go index 8cfb0d04e..d6b86229c 100644 --- a/pkg/machine/ignition_schema.go +++ b/pkg/machine/ignition_schema.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine diff --git a/pkg/machine/ignition_windows.go b/pkg/machine/ignition_windows.go index c0de48bd3..0fcc06273 100644 --- a/pkg/machine/ignition_windows.go +++ b/pkg/machine/ignition_windows.go @@ -1,4 +1,5 @@ -//+build windows +//go:build windows +// +build windows package machine diff --git a/pkg/machine/keys.go b/pkg/machine/keys.go index 711b091f0..15c1f73d8 100644 --- a/pkg/machine/keys.go +++ b/pkg/machine/keys.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine diff --git a/pkg/machine/machine_unsupported.go b/pkg/machine/machine_unsupported.go index da1437984..a12140e16 100644 --- a/pkg/machine/machine_unsupported.go +++ b/pkg/machine/machine_unsupported.go @@ -1,3 +1,4 @@ +//go:build !amd64 && !arm64 // +build !amd64,!arm64 package machine diff --git a/pkg/machine/pull.go b/pkg/machine/pull.go index cf1e708b1..26abedfcd 100644 --- a/pkg/machine/pull.go +++ b/pkg/machine/pull.go @@ -1,3 +1,4 @@ +//go:build amd64 || arm64 // +build amd64 arm64 package machine diff --git a/pkg/machine/qemu/config.go b/pkg/machine/qemu/config.go index b39334be0..211d96ccb 100644 --- a/pkg/machine/qemu/config.go +++ b/pkg/machine/qemu/config.go @@ -61,6 +61,6 @@ type Monitor struct { var ( // defaultQMPTimeout is the timeout duration for the - // qmp monitor interactions + // qmp monitor interactions. defaultQMPTimeout time.Duration = 2 * time.Second ) diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 3b4548c17..287b93612 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -34,7 +34,7 @@ import ( var ( qemuProvider = &Provider{} - // vmtype refers to qemu (vs libvirt, krun, etc) + // vmtype refers to qemu (vs libvirt, krun, etc). vmtype = "qemu" ) @@ -98,7 +98,7 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) { return nil, err } - cmd := append([]string{execPath}) + cmd := []string{execPath} // Add memory cmd = append(cmd, []string{"-m", strconv.Itoa(int(vm.Memory))}...) // Add cpus @@ -134,7 +134,7 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) { // LoadByName reads a json file that describes a known qemu vm // and returns a vm instance func (p *Provider) LoadVMByName(name string) (machine.VM, error) { - vm := new(MachineVM) + vm := &MachineVM{UID: -1} // posix reserves -1, so use it to signify undefined vmConfigDir, err := machine.GetConfDir(vmtype) if err != nil { return nil, err @@ -278,7 +278,9 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { fmt.Println("An ignition path was provided. No SSH connection was added to Podman") } // Write the JSON file - v.writeConfig() + if err := v.writeConfig(); err != nil { + return false, fmt.Errorf("writing JSON file: %w", err) + } // User has provided ignition file so keygen // will be skipped. @@ -370,9 +372,13 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { conn net.Conn err error qemuSocketConn net.Conn - wait time.Duration = time.Millisecond * 500 + wait = time.Millisecond * 500 ) + if v.isIncompatible() { + logrus.Errorf("machine %q is incompatible with this release of podman and needs to be recreated, starting for recovery only", v.Name) + } + forwardSock, forwardState, err := v.startHostNetworking() if err != nil { return errors.Errorf("unable to start host networking: %q", err) @@ -424,13 +430,29 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { // Disable graphic window when not in debug mode // Done in start, so we're not suck with the debug level we used on init - if logrus.GetLevel() != logrus.DebugLevel { + if !logrus.IsLevelEnabled(logrus.DebugLevel) { cmd = append(cmd, "-display", "none") } _, err = os.StartProcess(v.CmdLine[0], cmd, attr) if err != nil { - return err + // check if qemu was not found + if !errors.Is(err, os.ErrNotExist) { + return err + } + // lookup qemu again maybe the path was changed, https://github.com/containers/podman/issues/13394 + cfg, err := config.Default() + if err != nil { + return err + } + cmd[0], err = cfg.FindHelperBinary(QemuCommand, true) + if err != nil { + return err + } + _, err = os.StartProcess(cmd[0], cmd, attr) + if err != nil { + return err + } } fmt.Println("Waiting for VM ...") socketPath, err := getRuntimeDir() @@ -506,7 +528,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { } } - waitAPIAndPrintInfo(forwardState, forwardSock, v.Rootful, v.Name) + v.waitAPIAndPrintInfo(forwardState, forwardSock) return nil } @@ -622,7 +644,8 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error { } if err := qmpMonitor.Disconnect(); err != nil { - return nil + // FIXME: this error should probably be returned + return nil // nolint: nilerr } disconnected = true @@ -751,7 +774,8 @@ func (v *MachineVM) isRunning() (bool, error) { // Check if we can dial it monitor, err := qmp.NewSocketMonitor(v.QMPMonitor.Network, v.QMPMonitor.Address, v.QMPMonitor.Timeout) if err != nil { - return false, nil + // FIXME: this error should probably be returned + return false, nil // nolint: nilerr } if err := monitor.Connect(); err != nil { return false, err @@ -774,7 +798,7 @@ func (v *MachineVM) isRunning() (bool, error) { func (v *MachineVM) isListening() bool { // Check if we can dial it - conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", "localhost", v.Port), 10*time.Millisecond) + conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", "127.0.0.1", v.Port), 10*time.Millisecond) if err != nil { return false } @@ -975,7 +999,11 @@ func (v *MachineVM) startHostNetworking() (string, apiForwardingState, error) { // Add the ssh port cmd = append(cmd, []string{"-ssh-port", fmt.Sprintf("%d", v.Port)}...) - cmd, forwardSock, state := v.setupAPIForwarding(cmd) + var forwardSock string + var state apiForwardingState + if !v.isIncompatible() { + cmd, forwardSock, state = v.setupAPIForwarding(cmd) + } if logrus.GetLevel() == logrus.DebugLevel { cmd = append(cmd, "--debug") @@ -1043,6 +1071,10 @@ func (v *MachineVM) setupAPIForwarding(cmd []string) ([]string, string, apiForwa return cmd, dockerSock, dockerGlobal } +func (v *MachineVM) isIncompatible() bool { + return v.UID == -1 +} + func (v *MachineVM) getForwardSocketPath() (string, error) { path, err := machine.GetDataDir(v.Name) if err != nil { @@ -1085,10 +1117,13 @@ func waitAndPingAPI(sock string) { Transport: &http.Transport{ DialContext: func(context.Context, string, string) (net.Conn, error) { con, err := net.DialTimeout("unix", sock, apiUpTimeout) - if err == nil { - con.SetDeadline(time.Now().Add(apiUpTimeout)) + if err != nil { + return nil, err } - return con, err + if err := con.SetDeadline(time.Now().Add(apiUpTimeout)); err != nil { + return nil, err + } + return con, nil }, }, } @@ -1102,46 +1137,66 @@ func waitAndPingAPI(sock string) { } } -func waitAPIAndPrintInfo(forwardState apiForwardingState, forwardSock string, rootFul bool, name string) { - if forwardState != noForwarding { - suffix := "" - if name != machine.DefaultMachineName { - suffix = " " + name - } - waitAndPingAPI(forwardSock) - if !rootFul { - fmt.Printf("\nThis machine is currently configured in rootless mode. If your containers\n") - fmt.Printf("require root permissions (e.g. ports < 1024), or if you run into compatibility\n") - fmt.Printf("issues with non-podman clients, you can switch using the following command: \n") - fmt.Printf("\n\tpodman machine set --rootful%s\n\n", suffix) - } +func (v *MachineVM) waitAPIAndPrintInfo(forwardState apiForwardingState, forwardSock string) { + suffix := "" + if v.Name != machine.DefaultMachineName { + suffix = " " + v.Name + } - fmt.Printf("API forwarding listening on: %s\n", forwardSock) - if forwardState == dockerGlobal { - fmt.Printf("Docker API clients default to this address. You do not need to set DOCKER_HOST.\n\n") - } else { - stillString := "still " - switch forwardState { - case notInstalled: - fmt.Printf("\nThe system helper service is not installed; the default Docker API socket\n") - fmt.Printf("address can't be used by podman. ") - if helper := findClaimHelper(); len(helper) > 0 { - fmt.Printf("If you would like to install it run the\nfollowing commands:\n") - fmt.Printf("\n\tsudo %s install\n", helper) - fmt.Printf("\tpodman machine stop%s; podman machine start%s\n\n", suffix, suffix) - } - case machineLocal: - fmt.Printf("\nAnother process was listening on the default Docker API socket address.\n") - case claimUnsupported: - fallthrough - default: - stillString = "" - } + if v.isIncompatible() { + fmt.Fprintf(os.Stderr, "\n!!! ACTION REQUIRED: INCOMPATIBLE MACHINE !!!\n") - fmt.Printf("You can %sconnect Docker API clients by setting DOCKER_HOST using the\n", stillString) - fmt.Printf("following command in your terminal session:\n") - fmt.Printf("\n\texport DOCKER_HOST='unix://%s'\n\n", forwardSock) + fmt.Fprintf(os.Stderr, "\nThis machine was created by an older podman release that is incompatible\n") + fmt.Fprintf(os.Stderr, "with this release of podman. It has been started in a limited operational\n") + fmt.Fprintf(os.Stderr, "mode to allow you to copy any necessary files before recreating it. This\n") + fmt.Fprintf(os.Stderr, "can be accomplished with the following commands:\n\n") + fmt.Fprintf(os.Stderr, "\t# Login and copy desired files (Optional)\n") + fmt.Fprintf(os.Stderr, "\t# podman machine ssh%s tar cvPf - /path/to/files > backup.tar\n\n", suffix) + fmt.Fprintf(os.Stderr, "\t# Recreate machine (DESTRUCTIVE!) \n") + fmt.Fprintf(os.Stderr, "\tpodman machine stop%s\n", suffix) + fmt.Fprintf(os.Stderr, "\tpodman machine rm -f%s\n", suffix) + fmt.Fprintf(os.Stderr, "\tpodman machine init --now%s\n\n", suffix) + fmt.Fprintf(os.Stderr, "\t# Copy back files (Optional)\n") + fmt.Fprintf(os.Stderr, "\t# cat backup.tar | podman machine ssh%s tar xvPf - \n\n", suffix) + } + + if forwardState == noForwarding { + return + } + + waitAndPingAPI(forwardSock) + if !v.Rootful { + fmt.Printf("\nThis machine is currently configured in rootless mode. If your containers\n") + fmt.Printf("require root permissions (e.g. ports < 1024), or if you run into compatibility\n") + fmt.Printf("issues with non-podman clients, you can switch using the following command: \n") + fmt.Printf("\n\tpodman machine set --rootful%s\n\n", suffix) + } + + fmt.Printf("API forwarding listening on: %s\n", forwardSock) + if forwardState == dockerGlobal { + fmt.Printf("Docker API clients default to this address. You do not need to set DOCKER_HOST.\n\n") + } else { + stillString := "still " + switch forwardState { + case notInstalled: + fmt.Printf("\nThe system helper service is not installed; the default Docker API socket\n") + fmt.Printf("address can't be used by podman. ") + if helper := findClaimHelper(); len(helper) > 0 { + fmt.Printf("If you would like to install it run the\nfollowing commands:\n") + fmt.Printf("\n\tsudo %s install\n", helper) + fmt.Printf("\tpodman machine stop%s; podman machine start%s\n\n", suffix, suffix) + } + case machineLocal: + fmt.Printf("\nAnother process was listening on the default Docker API socket address.\n") + case claimUnsupported: + fallthrough + default: + stillString = "" } + + fmt.Printf("You can %sconnect Docker API clients by setting DOCKER_HOST using the\n", stillString) + fmt.Printf("following command in your terminal session:\n") + fmt.Printf("\n\texport DOCKER_HOST='unix://%s'\n\n", forwardSock) } } diff --git a/pkg/machine/qemu/machine_unsupported.go b/pkg/machine/qemu/machine_unsupported.go index e3ce05e3d..794e710f9 100644 --- a/pkg/machine/qemu/machine_unsupported.go +++ b/pkg/machine/qemu/machine_unsupported.go @@ -1,3 +1,4 @@ +//go:build (!amd64 && !arm64) || windows // +build !amd64,!arm64 windows package qemu diff --git a/pkg/machine/wsl/machine_unsupported.go b/pkg/machine/wsl/machine_unsupported.go index 043c5d729..856f9dd0c 100644 --- a/pkg/machine/wsl/machine_unsupported.go +++ b/pkg/machine/wsl/machine_unsupported.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package wsl diff --git a/pkg/rootless/rootless.go b/pkg/rootless/rootless.go index 93b4e2e9f..13f8078e2 100644 --- a/pkg/rootless/rootless.go +++ b/pkg/rootless/rootless.go @@ -1,6 +1,8 @@ package rootless import ( + "errors" + "fmt" "os" "sort" "sync" @@ -8,7 +10,6 @@ import ( "github.com/containers/storage/pkg/lockfile" "github.com/opencontainers/runc/libcontainer/user" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" ) // TryJoinPauseProcess attempts to join the namespaces of the pause PID via @@ -16,12 +17,15 @@ import ( // file. func TryJoinPauseProcess(pausePidPath string) (bool, int, error) { if _, err := os.Stat(pausePidPath); err != nil { - return false, -1, nil + if errors.Is(err, os.ErrNotExist) { + return false, -1, nil + } + return false, -1, err } became, ret, err := TryJoinFromFilePaths("", false, []string{pausePidPath}) if err == nil { - return became, ret, err + return became, ret, nil } // It could not join the pause process, let's lock the file before trying to delete it. @@ -31,7 +35,7 @@ func TryJoinPauseProcess(pausePidPath string) (bool, int, error) { if os.IsNotExist(err) { return false, -1, nil } - return false, -1, errors.Wrapf(err, "error acquiring lock on %s", pausePidPath) + return false, -1, fmt.Errorf("error acquiring lock on %s: %w", pausePidPath, err) } pidFileLock.Lock() @@ -46,7 +50,7 @@ func TryJoinPauseProcess(pausePidPath string) (bool, int, error) { if err != nil { // It is still failing. We can safely remove it. os.Remove(pausePidPath) - return false, -1, nil + return false, -1, nil // nolint: nilerr } return became, ret, err } diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index a0b6edcfb..786e28093 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -1,3 +1,4 @@ +//go:build linux && cgo // +build linux,cgo package rootless diff --git a/pkg/rootless/rootless_unsupported.go b/pkg/rootless/rootless_unsupported.go index 7dfb4a4b2..fe164e235 100644 --- a/pkg/rootless/rootless_unsupported.go +++ b/pkg/rootless/rootless_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux || !cgo // +build !linux !cgo package rootless diff --git a/pkg/rootlessport/rootlessport_linux.go b/pkg/rootlessport/rootlessport_linux.go index b89a92d1e..6918a7e8c 100644 --- a/pkg/rootlessport/rootlessport_linux.go +++ b/pkg/rootlessport/rootlessport_linux.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux // Package rootlessport provides reexec for RootlessKit-based port forwarder. diff --git a/pkg/servicereaper/service.go b/pkg/servicereaper/service.go index e105148f0..61445bc19 100644 --- a/pkg/servicereaper/service.go +++ b/pkg/servicereaper/service.go @@ -1,4 +1,5 @@ -//+build linux +//go:build linux +// +build linux package servicereaper diff --git a/pkg/signal/signal_common.go b/pkg/signal/signal_common.go index 8ff4b4dbf..5ea67843a 100644 --- a/pkg/signal/signal_common.go +++ b/pkg/signal/signal_common.go @@ -25,7 +25,7 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) { } // ParseSignalNameOrNumber translates a string to a valid syscall signal. Input -// can be a name or number representation i.e. "KILL" "9" +// can be a name or number representation i.e. "KILL" "9". func ParseSignalNameOrNumber(rawSignal string) (syscall.Signal, error) { basename := strings.TrimPrefix(rawSignal, "-") s, err := ParseSignal(basename) diff --git a/pkg/signal/signal_linux.go b/pkg/signal/signal_linux.go index 305b9d21f..21e09c9fe 100644 --- a/pkg/signal/signal_linux.go +++ b/pkg/signal/signal_linux.go @@ -1,5 +1,5 @@ -// +build linux -// +build !mips,!mipsle,!mips64,!mips64le +//go:build linux && !mips && !mipsle && !mips64 && !mips64le +// +build linux,!mips,!mipsle,!mips64,!mips64le // Signal handling for Linux only. package signal diff --git a/pkg/signal/signal_linux_mipsx.go b/pkg/signal/signal_linux_mipsx.go index 45c9d5af1..52b07aaf4 100644 --- a/pkg/signal/signal_linux_mipsx.go +++ b/pkg/signal/signal_linux_mipsx.go @@ -1,3 +1,4 @@ +//go:build linux && (mips || mipsle || mips64 || mips64le) // +build linux // +build mips mipsle mips64 mips64le diff --git a/pkg/signal/signal_unix.go b/pkg/signal/signal_unix.go index f35abddc1..c0aa62d21 100644 --- a/pkg/signal/signal_unix.go +++ b/pkg/signal/signal_unix.go @@ -1,3 +1,4 @@ +//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd || solaris || zos // +build aix darwin dragonfly freebsd netbsd openbsd solaris zos // Signal handling for Linux only. diff --git a/pkg/signal/signal_unsupported.go b/pkg/signal/signal_unsupported.go index 45946f142..d8bba7c90 100644 --- a/pkg/signal/signal_unsupported.go +++ b/pkg/signal/signal_unsupported.go @@ -1,3 +1,4 @@ +//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos // Signal handling for Linux only. diff --git a/pkg/specgen/config_unsupported.go b/pkg/specgen/config_unsupported.go index 70a60ac47..a6bf77277 100644 --- a/pkg/specgen/config_unsupported.go +++ b/pkg/specgen/config_unsupported.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package specgen diff --git a/pkg/specgen/generate/config_linux.go b/pkg/specgen/generate/config_linux.go index a5772bc6a..35d7f0252 100644 --- a/pkg/specgen/generate/config_linux.go +++ b/pkg/specgen/generate/config_linux.go @@ -262,8 +262,8 @@ func addDevice(g *generate.Generator, device string) error { // ParseDevice parses device mapping string to a src, dest & permissions string func ParseDevice(device string) (string, string, string, error) { //nolint - src := "" - dst := "" + var src string + var dst string permissions := "rwm" arr := strings.Split(device, ":") switch len(arr) { diff --git a/pkg/specgen/generate/config_linux_cgo.go b/pkg/specgen/generate/config_linux_cgo.go index 239655c72..efab6679a 100644 --- a/pkg/specgen/generate/config_linux_cgo.go +++ b/pkg/specgen/generate/config_linux_cgo.go @@ -1,3 +1,4 @@ +//go:build linux && cgo // +build linux,cgo package generate diff --git a/pkg/specgen/generate/config_linux_nocgo.go b/pkg/specgen/generate/config_linux_nocgo.go index 9ead739a7..99b0c4eb2 100644 --- a/pkg/specgen/generate/config_linux_nocgo.go +++ b/pkg/specgen/generate/config_linux_nocgo.go @@ -1,3 +1,4 @@ +//go:build linux && !cgo // +build linux,!cgo package generate diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index 64669f34d..0e9d33dd8 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -338,8 +338,8 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error { } // ConfigToSpec takes a completed container config and converts it back into a specgenerator for purposes of cloning an exisiting container -func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, contaierID string) (*libpod.Container, error) { - c, err := rt.LookupContainer(contaierID) +func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, containerID string) (*libpod.Container, error) { + c, err := rt.LookupContainer(containerID) if err != nil { return nil, err } diff --git a/pkg/specgen/generate/ports_bench_test.go b/pkg/specgen/generate/ports_bench_test.go index f208a34c5..f65cd2f15 100644 --- a/pkg/specgen/generate/ports_bench_test.go +++ b/pkg/specgen/generate/ports_bench_test.go @@ -9,7 +9,7 @@ import ( func benchmarkParsePortMapping(b *testing.B, ports []types.PortMapping) { for n := 0; n < b.N; n++ { - ParsePortMapping(ports, nil) + _, _ = ParsePortMapping(ports, nil) } } diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go index 9c6709905..988c29832 100644 --- a/pkg/specgen/generate/security.go +++ b/pkg/specgen/generate/security.go @@ -146,6 +146,10 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, configSpec := g.Config configSpec.Process.Capabilities.Ambient = []string{} + + // Always unset the inheritable capabilities similarly to what the Linux kernel does + // They are used only when using capabilities with uid != 0. + configSpec.Process.Capabilities.Inheritable = []string{} configSpec.Process.Capabilities.Bounding = caplist user := strings.Split(s.User, ":")[0] @@ -153,7 +157,6 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, if (user == "" && s.UserNS.NSMode != specgen.KeepID) || user == "root" || user == "0" { configSpec.Process.Capabilities.Effective = caplist configSpec.Process.Capabilities.Permitted = caplist - configSpec.Process.Capabilities.Inheritable = caplist } else { mergedCaps, err := capabilities.MergeCapabilities(nil, s.CapAdd, nil) if err != nil { @@ -175,12 +178,12 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, } configSpec.Process.Capabilities.Effective = userCaps configSpec.Process.Capabilities.Permitted = userCaps - configSpec.Process.Capabilities.Inheritable = userCaps // Ambient capabilities were added to Linux 4.3. Set ambient // capabilities only when the kernel supports them. if supportAmbientCapabilities() { configSpec.Process.Capabilities.Ambient = userCaps + configSpec.Process.Capabilities.Inheritable = userCaps } } diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go index b87da61fb..688cc2337 100644 --- a/pkg/specgenutil/specgen.go +++ b/pkg/specgenutil/specgen.go @@ -847,7 +847,8 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start if len(cmdArr) == 0 { return nil, errors.New("Must define a healthcheck command for all healthchecks") } - concat := "" + + var concat string if cmdArr[0] == "CMD" || cmdArr[0] == "none" { // this is for compat, we are already split properly for most compat cases cmdArr = strings.Fields(inCmd) } else if cmdArr[0] != "CMD-SHELL" { // this is for podman side of things, won't contain the keywords diff --git a/pkg/systemd/dbus.go b/pkg/systemd/dbus.go index 1b1bc8be9..44feb8308 100644 --- a/pkg/systemd/dbus.go +++ b/pkg/systemd/dbus.go @@ -24,7 +24,6 @@ func IsSystemdSessionValid(uid int) bool { if rootless.IsRootless() { conn, err = GetLogindConnection(rootless.GetRootlessUID()) - object = conn.Object(dbusDest, godbus.ObjectPath(dbusPath)) if err != nil { //unable to fetch systemd object for logind logrus.Debugf("systemd-logind: %s", err) diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go index c01bb1baf..e11aed771 100644 --- a/pkg/systemd/generate/containers.go +++ b/pkg/systemd/generate/containers.go @@ -362,7 +362,9 @@ func executeContainerTemplate(info *containerInfo, options entities.GenerateSyst fs.StringArrayP("env", "e", nil, "") fs.String("sdnotify", "", "") fs.String("restart", "", "") - fs.Parse(remainingCmd) + if err := fs.Parse(remainingCmd); err != nil { + return "", fmt.Errorf("parsing remaining command-line arguments: %w", err) + } remainingCmd = filterCommonContainerFlags(remainingCmd, fs.NArg()) // If the container is in a pod, make sure that the diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go index 78ae6391b..15b598ae8 100644 --- a/pkg/systemd/generate/pods.go +++ b/pkg/systemd/generate/pods.go @@ -335,7 +335,9 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions) fs.SetInterspersed(false) fs.String("name", "", "") fs.Bool("replace", false, "") - fs.Parse(podCreateArgs) + if err := fs.Parse(podCreateArgs); err != nil { + return "", fmt.Errorf("parsing remaining command-line arguments: %w", err) + } hasNameParam := fs.Lookup("name").Changed hasReplaceParam, err := fs.GetBool("replace") diff --git a/pkg/terminal/console_unix.go b/pkg/terminal/console_unix.go index 6eee6aa2f..53290be24 100644 --- a/pkg/terminal/console_unix.go +++ b/pkg/terminal/console_unix.go @@ -1,8 +1,9 @@ +//go:build !windows // +build !windows package terminal -// SetConsole for non-windows environments is a no-op +// SetConsole for non-windows environments is a no-op. func SetConsole() error { return nil } diff --git a/pkg/terminal/console_windows.go b/pkg/terminal/console_windows.go index 9a636d681..1a7da3335 100644 --- a/pkg/terminal/console_windows.go +++ b/pkg/terminal/console_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package terminal diff --git a/pkg/util/camelcase/camelcase.go b/pkg/util/camelcase/camelcase.go index d27ac00d6..eaf7c0178 100644 --- a/pkg/util/camelcase/camelcase.go +++ b/pkg/util/camelcase/camelcase.go @@ -51,10 +51,10 @@ func Split(src string) (entries []string) { } entries = []string{} var runes [][]rune - lastClass := 0 - class := 0 + var lastClass int // split into fields based on class of unicode character for _, r := range src { + var class int switch { case unicode.IsLower(r): class = 1 diff --git a/pkg/util/mountOpts_other.go b/pkg/util/mountOpts_other.go index 6a34942e5..64b4dd1d9 100644 --- a/pkg/util/mountOpts_other.go +++ b/pkg/util/mountOpts_other.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package util diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 925ff9830..1beb3b28e 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -727,7 +727,7 @@ func SocketPath() (string, error) { func LookupUser(name string) (*user.User, error) { // Assume UID look up first, if it fails lookup by username if u, err := user.LookupId(name); err == nil { - return u, err + return u, nil } return user.Lookup(name) } diff --git a/pkg/util/utils_darwin.go b/pkg/util/utils_darwin.go index 33a46a5d4..66ae85e9c 100644 --- a/pkg/util/utils_darwin.go +++ b/pkg/util/utils_darwin.go @@ -1,4 +1,5 @@ -//+build darwin +//go:build darwin +// +build darwin package util diff --git a/pkg/util/utils_supported.go b/pkg/util/utils_supported.go index 848b35a45..50e4b1b7b 100644 --- a/pkg/util/utils_supported.go +++ b/pkg/util/utils_supported.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package util diff --git a/pkg/util/utils_unsupported.go b/pkg/util/utils_unsupported.go index 62805d7c8..896346493 100644 --- a/pkg/util/utils_unsupported.go +++ b/pkg/util/utils_unsupported.go @@ -1,3 +1,4 @@ +//go:build darwin || windows // +build darwin windows package util diff --git a/pkg/util/utils_windows.go b/pkg/util/utils_windows.go index 46ca5e7f1..2732124f2 100644 --- a/pkg/util/utils_windows.go +++ b/pkg/util/utils_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package util |