diff options
Diffstat (limited to 'pkg')
30 files changed, 443 insertions, 192 deletions
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/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go index 250736579..b823a56b6 100644 --- a/pkg/api/handlers/libpod/manifests.go +++ b/pkg/api/handlers/libpod/manifests.go @@ -162,13 +162,35 @@ func ManifestAdd(w http.ResponseWriter, r *http.Request) { // Wrapper to support 3.x with 4.x libpod query := struct { entities.ManifestAddOptions - Images []string + Images []string + TLSVerify bool `schema:"tlsVerify"` }{} if err := json.NewDecoder(r.Body).Decode(&query); err != nil { utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) return } + authconf, authfile, err := auth.GetCredentials(r) + if err != nil { + utils.Error(w, http.StatusBadRequest, err) + return + } + defer auth.RemoveAuthfile(authfile) + var username, password string + if authconf != nil { + username = authconf.Username + password = authconf.Password + } + query.ManifestAddOptions.Authfile = authfile + query.ManifestAddOptions.Username = username + query.ManifestAddOptions.Password = password + if sys := runtime.SystemContext(); sys != nil { + query.ManifestAddOptions.CertDir = sys.DockerCertPath + } + if _, found := r.URL.Query()["tlsVerify"]; found { + query.SkipTLSVerify = types.NewOptionalBool(!query.TLSVerify) + } + name := utils.GetName(r) if _, err := runtime.LibimageRuntime().LookupManifestList(name); err != nil { utils.Error(w, http.StatusNotFound, err) @@ -271,7 +293,7 @@ func ManifestPushV3(w http.ResponseWriter, r *http.Request) { utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "error pushing image %q", query.Destination)) return } - utils.WriteResponse(w, http.StatusOK, digest) + utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: digest}) } // ManifestPush push image to registry @@ -350,6 +372,24 @@ func ManifestModify(w http.ResponseWriter, r *http.Request) { return } + authconf, authfile, err := auth.GetCredentials(r) + if err != nil { + utils.Error(w, http.StatusBadRequest, err) + return + } + defer auth.RemoveAuthfile(authfile) + var username, password string + if authconf != nil { + username = authconf.Username + password = authconf.Password + } + body.ManifestAddOptions.Authfile = authfile + body.ManifestAddOptions.Username = username + body.ManifestAddOptions.Password = password + if sys := runtime.SystemContext(); sys != nil { + body.ManifestAddOptions.CertDir = sys.DockerCertPath + } + var report entities.ManifestModifyReport switch { case strings.EqualFold("update", body.Operation): @@ -401,7 +441,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/bindings/containers/attach.go b/pkg/bindings/containers/attach.go index 0c6ebdd2f..80702ea98 100644 --- a/pkg/bindings/containers/attach.go +++ b/pkg/bindings/containers/attach.go @@ -242,7 +242,7 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri } } case fd == 3: - return fmt.Errorf("error from service from stream: %s", frame) + return fmt.Errorf("from service from stream: %s", frame) default: return fmt.Errorf("unrecognized channel '%d' in header, 0-3 supported", fd) } @@ -562,7 +562,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar } } case fd == 3: - return fmt.Errorf("error from service from stream: %s", frame) + return fmt.Errorf("from service from stream: %s", frame) default: return fmt.Errorf("unrecognized channel '%d' in header, 0-3 supported", fd) } diff --git a/pkg/bindings/containers/logs.go b/pkg/bindings/containers/logs.go index 7f7f07395..8ea8ed7fa 100644 --- a/pkg/bindings/containers/logs.go +++ b/pkg/bindings/containers/logs.go @@ -57,7 +57,7 @@ func Logs(ctx context.Context, nameOrID string, options *LogOptions, stdoutChan, case 2: stderrChan <- string(frame) case 3: - return errors.New("error from service in stream: " + string(frame)) + return errors.New("from service in stream: " + string(frame)) default: return fmt.Errorf("unrecognized input header: %d", fd) } diff --git a/pkg/bindings/errors.go b/pkg/bindings/errors.go index 44973eb41..eb95764ba 100644 --- a/pkg/bindings/errors.go +++ b/pkg/bindings/errors.go @@ -54,6 +54,6 @@ func CheckResponseCode(inError error) (int, error) { case *errorhandling.PodConflictErrorModel: return e.Code(), nil default: - return -1, errors.New("error is not type ErrorModel") + return -1, errors.New("is not type ErrorModel") } } diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go index c508cb767..e1b427742 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -241,7 +241,9 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO params.Add("platform", platform) } } - if contextDir, err := filepath.EvalSymlinks(options.ContextDirectory); err == nil { + var err error + var contextDir string + if contextDir, err = filepath.EvalSymlinks(options.ContextDirectory); err == nil { options.ContextDirectory = contextDir } @@ -301,7 +303,6 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO var ( headers http.Header - err error ) if options.SystemContext != nil && options.SystemContext.DockerAuthConfig != nil { headers, err = auth.MakeXRegistryAuthHeader(options.SystemContext, options.SystemContext.DockerAuthConfig.Username, options.SystemContext.DockerAuthConfig.Password) @@ -325,7 +326,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO } } - contextDir, err := filepath.Abs(options.ContextDirectory) + contextDir, err = filepath.Abs(options.ContextDirectory) if err != nil { logrus.Errorf("Cannot find absolute path of %v: %v", options.ContextDirectory, err) return nil, err @@ -556,16 +557,27 @@ func nTar(excludes []string, sources ...string) (io.ReadCloser, error) { merr = multierror.Append(merr, err) return } - err = filepath.Walk(s, func(path string, info os.FileInfo, err error) error { if err != nil { return err } - if path == s { - return nil // skip root dir + // check if what we are given is an empty dir, if so then continue w/ it. Else return. + // if we are given a file or a symlink, we do not want to exclude it. + if info.IsDir() && s == path { + var p *os.File + p, err = os.Open(path) + if err != nil { + return err + } + defer p.Close() + _, err = p.Readdir(1) + if err != io.EOF { + return nil // non empty root dir, need to return + } else if err != nil { + logrus.Errorf("While reading directory %v: %v", path, err) + } } - name := filepath.ToSlash(strings.TrimPrefix(path, s+string(filepath.Separator))) excluded, err := pm.Matches(name) // nolint:staticcheck diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go index 458cb913a..70b3819f5 100644 --- a/pkg/bindings/manifests/manifests.go +++ b/pkg/bindings/manifests/manifests.go @@ -2,20 +2,24 @@ package manifests import ( "context" - "errors" "fmt" + "io/ioutil" "net/http" - "net/url" "strconv" "strings" "github.com/blang/semver" "github.com/containers/image/v5/manifest" + imageTypes "github.com/containers/image/v5/types" "github.com/containers/podman/v4/pkg/api/handlers" + "github.com/containers/podman/v4/pkg/auth" "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 @@ -93,15 +97,19 @@ func Add(ctx context.Context, name string, options *AddOptions) (string, error) if bindings.ServiceVersion(ctx).GTE(semver.MustParse("4.0.0")) { optionsv4 := ModifyOptions{ - All: options.All, - Annotations: options.Annotation, - Arch: options.Arch, - Features: options.Features, - Images: options.Images, - OS: options.OS, - OSFeatures: nil, - OSVersion: options.OSVersion, - Variant: options.Variant, + All: options.All, + Annotations: options.Annotation, + Arch: options.Arch, + Features: options.Features, + Images: options.Images, + OS: options.OS, + OSFeatures: nil, + OSVersion: options.OSVersion, + Variant: options.Variant, + Username: options.Username, + Password: options.Password, + Authfile: options.Authfile, + SkipTLSVerify: options.SkipTLSVerify, } optionsv4.WithOperation("update") return Modify(ctx, name, options.Images, &optionsv4) @@ -118,40 +126,27 @@ func Add(ctx context.Context, name string, options *AddOptions) (string, error) } reader := strings.NewReader(opts) - headers := make(http.Header) - v := version.APIVersion[version.Libpod][version.MinimalAPI] - headers.Add("API-Version", - fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)) - response, err := conn.DoRequest(ctx, reader, http.MethodPost, "/manifests/%s/add", nil, headers, name) + header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword()) if err != nil { return "", err } - defer response.Body.Close() - - var idr handlers.IDResponse - return idr.ID, response.Process(&idr) -} - -// 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) + params, err := options.ToParams() if err != nil { return "", err } + // SkipTLSVerify is special. We need to delete the param added by + // ToParams() and change the key and flip the bool + if options.SkipTLSVerify != nil { + params.Del("SkipTLSVerify") + params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify())) + } - headers := http.Header{} - headers.Add("API-Version", "3.4.0") + v := version.APIVersion[version.Libpod][version.MinimalAPI] + header.Add("API-Version", + fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)) - params := url.Values{} - params.Set("digest", digest) - response, err := conn.DoRequest(ctx, nil, http.MethodDelete, "/manifests/%s", params, headers, name) + response, err := conn.DoRequest(ctx, reader, http.MethodPost, "/manifests/%s/add", params, header, name) if err != nil { return "", err } @@ -161,6 +156,13 @@ func Remove(ctx context.Context, name, digest string, _ *RemoveOptions) (string, return idr.ID, response.Process(&idr) } +// 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) { + 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, // the name will be used instead. If the optional all boolean is specified, all images specified // in the list will be pushed as well. @@ -179,6 +181,14 @@ func Push(ctx context.Context, name, destination string, options *images.PushOpt return "", err } + header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword()) + if err != nil { + return "", err + } + v := version.APIVersion[version.Libpod][version.MinimalAPI] + header.Add("API-Version", + fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)) + params, err := options.ToParams() if err != nil { return "", err @@ -192,18 +202,18 @@ func Push(ctx context.Context, name, destination string, options *images.PushOpt var response *bindings.APIResponse if bindings.ServiceVersion(ctx).GTE(semver.MustParse("4.0.0")) { - response, err = conn.DoRequest(ctx, nil, http.MethodPost, "/manifests/%s/registry/%s", params, nil, name, destination) + response, err = conn.DoRequest(ctx, nil, http.MethodPost, "/manifests/%s/registry/%s", params, header, name, destination) } else { params.Set("image", name) params.Set("destination", destination) - response, err = conn.DoRequest(ctx, nil, http.MethodPost, "/manifests/%s/push", params, nil, name) + response, err = conn.DoRequest(ctx, nil, http.MethodPost, "/manifests/%s/push", params, header, name) } if err != nil { return "", err } defer response.Body.Close() - return idr.ID, err + return idr.ID, response.Process(&idr) } // Modify modifies the given manifest list using options and the optional list of images @@ -223,14 +233,58 @@ func Modify(ctx context.Context, name string, images []string, options *ModifyOp } reader := strings.NewReader(opts) - response, err := conn.DoRequest(ctx, reader, http.MethodPut, "/manifests/%s", nil, nil, name) + header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword()) + if err != nil { + return "", err + } + + params, err := options.ToParams() + if err != nil { + return "", err + } + // SkipTLSVerify is special. We need to delete the param added by + // ToParams() and change the key and flip the bool + if options.SkipTLSVerify != nil { + params.Del("SkipTLSVerify") + params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify())) + } + + response, err := conn.DoRequest(ctx, reader, http.MethodPut, "/manifests/%s", params, header, name) if err != nil { return "", err } 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/manifests/types.go b/pkg/bindings/manifests/types.go index 5ff28ee30..d0b0b2e71 100644 --- a/pkg/bindings/manifests/types.go +++ b/pkg/bindings/manifests/types.go @@ -20,14 +20,18 @@ type ExistsOptions struct { //go:generate go run ../generator/generator.go AddOptions // AddOptions are optional options for adding manifest lists type AddOptions struct { - All *bool - Annotation map[string]string - Arch *string - Features []string - Images []string - OS *string - OSVersion *string - Variant *string + All *bool + Annotation map[string]string + Arch *string + Features []string + Images []string + OS *string + OSVersion *string + Variant *string + Authfile *string + Password *string + Username *string + SkipTLSVerify *bool } //go:generate go run ../generator/generator.go RemoveOptions @@ -40,15 +44,18 @@ type RemoveOptions struct { type ModifyOptions struct { // Operation values are "update", "remove" and "annotate". This allows the service to // efficiently perform each update on a manifest list. - Operation *string - All *bool // All when true, operate on all images in a manifest list that may be included in Images - Annotations map[string]string // Annotations to add to manifest list - Arch *string // Arch overrides the architecture for the image - Features []string // Feature list for the image - Images []string // Images is an optional list of images to add/remove to/from manifest list depending on operation - OS *string // OS overrides the operating system for the image - OSFeatures []string // OS features for the image - OSVersion *string // OSVersion overrides the operating system for the image - Variant *string // Variant overrides the operating system variant for the image - + Operation *string + All *bool // All when true, operate on all images in a manifest list that may be included in Images + Annotations map[string]string // Annotations to add to manifest list + Arch *string // Arch overrides the architecture for the image + Features []string // Feature list for the image + Images []string // Images is an optional list of images to add/remove to/from manifest list depending on operation + OS *string // OS overrides the operating system for the image + OSFeatures []string // OS features for the image + OSVersion *string // OSVersion overrides the operating system for the image + Variant *string // Variant overrides the operating system variant for the image + Authfile *string + Password *string + Username *string + SkipTLSVerify *bool } diff --git a/pkg/bindings/manifests/types_add_options.go b/pkg/bindings/manifests/types_add_options.go index 0696a69b6..5ba1cc5fa 100644 --- a/pkg/bindings/manifests/types_add_options.go +++ b/pkg/bindings/manifests/types_add_options.go @@ -136,3 +136,63 @@ func (o *AddOptions) GetVariant() string { } return *o.Variant } + +// WithAuthfile set field Authfile to given value +func (o *AddOptions) WithAuthfile(value string) *AddOptions { + o.Authfile = &value + return o +} + +// GetAuthfile returns value of field Authfile +func (o *AddOptions) GetAuthfile() string { + if o.Authfile == nil { + var z string + return z + } + return *o.Authfile +} + +// WithPassword set field Password to given value +func (o *AddOptions) WithPassword(value string) *AddOptions { + o.Password = &value + return o +} + +// GetPassword returns value of field Password +func (o *AddOptions) GetPassword() string { + if o.Password == nil { + var z string + return z + } + return *o.Password +} + +// WithUsername set field Username to given value +func (o *AddOptions) WithUsername(value string) *AddOptions { + o.Username = &value + return o +} + +// GetUsername returns value of field Username +func (o *AddOptions) GetUsername() string { + if o.Username == nil { + var z string + return z + } + return *o.Username +} + +// WithSkipTLSVerify set field SkipTLSVerify to given value +func (o *AddOptions) WithSkipTLSVerify(value bool) *AddOptions { + o.SkipTLSVerify = &value + return o +} + +// GetSkipTLSVerify returns value of field SkipTLSVerify +func (o *AddOptions) GetSkipTLSVerify() bool { + if o.SkipTLSVerify == nil { + var z bool + return z + } + return *o.SkipTLSVerify +} diff --git a/pkg/bindings/manifests/types_modify_options.go b/pkg/bindings/manifests/types_modify_options.go index 6d75c1e5f..9d2ed2613 100644 --- a/pkg/bindings/manifests/types_modify_options.go +++ b/pkg/bindings/manifests/types_modify_options.go @@ -166,3 +166,63 @@ func (o *ModifyOptions) GetVariant() string { } return *o.Variant } + +// WithAuthfile set field Authfile to given value +func (o *ModifyOptions) WithAuthfile(value string) *ModifyOptions { + o.Authfile = &value + return o +} + +// GetAuthfile returns value of field Authfile +func (o *ModifyOptions) GetAuthfile() string { + if o.Authfile == nil { + var z string + return z + } + return *o.Authfile +} + +// WithPassword set field Password to given value +func (o *ModifyOptions) WithPassword(value string) *ModifyOptions { + o.Password = &value + return o +} + +// GetPassword returns value of field Password +func (o *ModifyOptions) GetPassword() string { + if o.Password == nil { + var z string + return z + } + return *o.Password +} + +// WithUsername set field Username to given value +func (o *ModifyOptions) WithUsername(value string) *ModifyOptions { + o.Username = &value + return o +} + +// GetUsername returns value of field Username +func (o *ModifyOptions) GetUsername() string { + if o.Username == nil { + var z string + return z + } + return *o.Username +} + +// WithSkipTLSVerify set field SkipTLSVerify to given value +func (o *ModifyOptions) WithSkipTLSVerify(value bool) *ModifyOptions { + o.SkipTLSVerify = &value + return o +} + +// GetSkipTLSVerify returns value of field SkipTLSVerify +func (o *ModifyOptions) GetSkipTLSVerify() bool { + if o.SkipTLSVerify == nil { + var z bool + return z + } + return *o.SkipTLSVerify +} 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/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/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_test.go b/pkg/domain/infra/abi/images_test.go index e38b9390d..311ab3ed7 100644 --- a/pkg/domain/infra/abi/images_test.go +++ b/pkg/domain/infra/abi/images_test.go @@ -48,7 +48,7 @@ func TestToDomainHistoryLayer(t *testing.T) { // r := DirectImageRuntime{m} // err := r.Delete(context.TODO(), actual, "fedora") // if err != nil { -// t.Errorf("error should be nil, got: %v", err) +// t.Errorf("should be nil, got: %v", err) // } // m.AssertExpectations(t) // } diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index 236d56053..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: @@ -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/tunnel/manifest.go b/pkg/domain/infra/tunnel/manifest.go index d2efed8d3..9ac3fdb83 100644 --- a/pkg/domain/infra/tunnel/manifest.go +++ b/pkg/domain/infra/tunnel/manifest.go @@ -50,6 +50,7 @@ func (ir *ImageEngine) ManifestInspect(_ context.Context, name string) ([]byte, func (ir *ImageEngine) ManifestAdd(_ context.Context, name string, imageNames []string, opts entities.ManifestAddOptions) (string, error) { options := new(manifests.AddOptions).WithAll(opts.All).WithArch(opts.Arch).WithVariant(opts.Variant) options.WithFeatures(opts.Features).WithImages(imageNames).WithOS(opts.OS).WithOSVersion(opts.OSVersion) + options.WithUsername(opts.Username).WithPassword(opts.Password).WithAuthfile(opts.Authfile) if len(opts.Annotation) != 0 { annotations := make(map[string]string) for _, annotationSpec := range opts.Annotation { @@ -61,6 +62,13 @@ func (ir *ImageEngine) ManifestAdd(_ context.Context, name string, imageNames [] } options.WithAnnotation(annotations) } + if s := opts.SkipTLSVerify; s != types.OptionalBoolUndefined { + if s == types.OptionalBoolTrue { + options.WithSkipTLSVerify(true) + } else { + options.WithSkipTLSVerify(false) + } + } id, err := manifests.Add(ir.ClientCtx, name, options) if err != nil { 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/k8s.io/api/core/v1/types.go b/pkg/k8s.io/api/core/v1/types.go index 833814bc6..a488e5f28 100644 --- a/pkg/k8s.io/api/core/v1/types.go +++ b/pkg/k8s.io/api/core/v1/types.go @@ -2024,7 +2024,7 @@ type TopologySpreadConstraint struct { // but giving higher precedence to topologies that would help reduce the // skew. // A constraint is considered "Unsatisfiable" for an incoming pod - // if and only if every possible node assigment for that pod would violate + // if and only if every possible node assignment for that pod would violate // "MaxSkew" on some topology. // For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same // labelSelector spread as 3/1/1: diff --git a/pkg/machine/pull.go b/pkg/machine/pull.go index 26abedfcd..7e6f01bad 100644 --- a/pkg/machine/pull.go +++ b/pkg/machine/pull.go @@ -129,7 +129,7 @@ func DownloadVMImage(downloadURL *url2.URL, localImagePath string) error { }() if resp.StatusCode != http.StatusOK { - return fmt.Errorf("error downloading VM image %s: %s", downloadURL, resp.Status) + return fmt.Errorf("downloading VM image %s: %s", downloadURL, resp.Status) } size := resp.ContentLength urlSplit := strings.Split(downloadURL.Path, "/") diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 1bd9fb51b..ffc90b2a0 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -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 @@ -317,7 +317,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { resize.Stdout = os.Stdout resize.Stderr = os.Stderr if err := resize.Run(); err != nil { - return false, errors.Errorf("error resizing image: %q", err) + return false, errors.Errorf("resizing image: %q", err) } } // If the user provides an ignition file, we need to @@ -430,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() @@ -782,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 } @@ -1062,7 +1078,7 @@ func (v *MachineVM) isIncompatible() bool { func (v *MachineVM) getForwardSocketPath() (string, error) { path, err := machine.GetDataDir(v.Name) if err != nil { - logrus.Errorf("Error resolving data dir: %s", err.Error()) + logrus.Errorf("Resolving data dir: %s", err.Error()) return "", nil } return filepath.Join(path, "podman.sock"), nil diff --git a/pkg/rootless/rootless.go b/pkg/rootless/rootless.go index 13f8078e2..d7143f549 100644 --- a/pkg/rootless/rootless.go +++ b/pkg/rootless/rootless.go @@ -35,7 +35,7 @@ func TryJoinPauseProcess(pausePidPath string) (bool, int, error) { if os.IsNotExist(err) { return false, -1, nil } - return false, -1, fmt.Errorf("error acquiring lock on %s: %w", pausePidPath, err) + return false, -1, fmt.Errorf("acquiring lock on %s: %w", pausePidPath, err) } pidFileLock.Lock() diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index 786e28093..cff6de5a3 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -146,7 +146,7 @@ func tryMappingTool(uid bool, pid int, hostID int, mappings []idtools.IDMap) err } if output, err := cmd.CombinedOutput(); err != nil { - logrus.Errorf("error running `%s`: %s", strings.Join(args, " "), output) + logrus.Errorf("running `%s`: %s", strings.Join(args, " "), output) return errors.Wrapf(err, "cannot setup namespace using %q", path) } return nil @@ -174,7 +174,7 @@ func joinUserAndMountNS(pid uint, pausePid string) (bool, int, error) { ret := C.reexec_in_user_namespace_wait(pidC, 0) if ret < 0 { - return false, -1, errors.New("error waiting for the re-exec process") + return false, -1, errors.New("waiting for the re-exec process") } return true, int(ret), nil @@ -374,7 +374,7 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo if fileOutput != nil { ret := C.reexec_in_user_namespace_wait(pidC, 0) if ret < 0 { - return false, -1, errors.New("error waiting for the re-exec process") + return false, -1, errors.New("waiting for the re-exec process") } return true, 0, nil @@ -391,11 +391,11 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo return joinUserAndMountNS(uint(pid), "") } } - return false, -1, errors.New("error setting up the process") + return false, -1, errors.New("setting up the process") } if b[0] != '0' { - return false, -1, errors.New("error setting up the process") + return false, -1, errors.New("setting up the process") } signals := []os.Signal{} @@ -425,7 +425,7 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo ret := C.reexec_in_user_namespace_wait(pidC, 0) if ret < 0 { - return false, -1, errors.New("error waiting for the re-exec process") + return false, -1, errors.New("waiting for the re-exec process") } return true, int(ret), nil diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index 64669f34d..118d80e2c 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -337,9 +337,9 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error { return nil } -// 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) +// ConfigToSpec takes a completed container config and converts it back into a specgenerator for purposes of cloning an existing container +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/kube/volume.go b/pkg/specgen/generate/kube/volume.go index d57cb5685..987f11569 100644 --- a/pkg/specgen/generate/kube/volume.go +++ b/pkg/specgen/generate/kube/volume.go @@ -76,7 +76,7 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error) return nil, errors.Wrap(err, "error checking HostPathSocket") } if st.Mode()&os.ModeSocket != os.ModeSocket { - return nil, errors.Errorf("error checking HostPathSocket: path %s is not a socket", hostPath.Path) + return nil, errors.Errorf("checking HostPathSocket: path %s is not a socket", hostPath.Path) } case v1.HostPathDirectory: 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/specgen/generate/storage.go b/pkg/specgen/generate/storage.go index 6dcc1b7bf..f30fc4671 100644 --- a/pkg/specgen/generate/storage.go +++ b/pkg/specgen/generate/storage.go @@ -292,7 +292,7 @@ func getVolumesFrom(volumesFrom []string, runtime *libpod.Runtime) (map[string]s // and append them in if we can find them. spec := ctr.Spec() if spec == nil { - return nil, nil, errors.Errorf("error retrieving container %s spec for volumes-from", ctr.ID()) + return nil, nil, errors.Errorf("retrieving container %s spec for volumes-from", ctr.ID()) } for _, mnt := range spec.Mounts { if mnt.Type != define.TypeBind { diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go index 688cc2337..186d3862b 100644 --- a/pkg/specgenutil/specgen.go +++ b/pkg/specgenutil/specgen.go @@ -976,7 +976,7 @@ func parseThrottleIOPsDevices(iopsDevices []string) (map[string]specs.LinuxThrot } func parseSecrets(secrets []string) ([]specgen.Secret, map[string]string, error) { - secretParseError := errors.New("error parsing secret") + secretParseError := errors.New("parsing secret") var mount []specgen.Secret envs := make(map[string]string) for _, val := range secrets { diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go index 15b598ae8..cd1486a82 100644 --- a/pkg/systemd/generate/pods.go +++ b/pkg/systemd/generate/pods.go @@ -141,7 +141,7 @@ func PodUnits(pod *libpod.Pod, options entities.GenerateSystemdOptions) (map[str // Error out if the pod has no infra container, which we require to be the // main service. if !pod.HasInfraContainer() { - return nil, errors.Errorf("error generating systemd unit files: Pod %q has no infra container", pod.Name()) + return nil, errors.Errorf("generating systemd unit files: Pod %q has no infra container", pod.Name()) } podInfo, err := generatePodInfo(pod, options) @@ -160,7 +160,7 @@ func PodUnits(pod *libpod.Pod, options entities.GenerateSystemdOptions) (map[str return nil, err } if len(containers) == 0 { - return nil, errors.Errorf("error generating systemd unit files: Pod %q has no containers", pod.Name()) + return nil, errors.Errorf("generating systemd unit files: Pod %q has no containers", pod.Name()) } graph, err := libpod.BuildContainerGraph(containers) if err != nil { diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 1beb3b28e..334a44a88 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -656,7 +656,7 @@ func CreateCidFile(cidfile string, id string) error { if os.IsExist(err) { return errors.Errorf("container id file exists. Ensure another container is not using it or delete %s", cidfile) } - return errors.Errorf("error opening cidfile %s", cidfile) + return errors.Errorf("opening cidfile %s", cidfile) } if _, err = cidFile.WriteString(id); err != nil { logrus.Error(err) |