aboutsummaryrefslogtreecommitdiff
path: root/pkg/bindings
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/bindings')
-rw-r--r--pkg/bindings/connection.go31
-rw-r--r--pkg/bindings/containers/archive.go4
-rw-r--r--pkg/bindings/containers/attach.go18
-rw-r--r--pkg/bindings/containers/containers.go11
-rw-r--r--pkg/bindings/containers/exec.go7
-rw-r--r--pkg/bindings/containers/logs.go2
-rw-r--r--pkg/bindings/containers/types.go3
-rw-r--r--pkg/bindings/containers/types_copy_options.go15
-rw-r--r--pkg/bindings/errors.go5
-rw-r--r--pkg/bindings/images/build.go36
-rw-r--r--pkg/bindings/images/build_unix.go2
-rw-r--r--pkg/bindings/images/images.go24
-rw-r--r--pkg/bindings/images/pull.go5
-rw-r--r--pkg/bindings/images/rm.go3
-rw-r--r--pkg/bindings/images/types.go9
-rw-r--r--pkg/bindings/images/types_push_options.go15
-rw-r--r--pkg/bindings/images/types_remove_options.go15
-rw-r--r--pkg/bindings/images/types_scp_options.go12
-rw-r--r--pkg/bindings/manifests/manifests.go31
-rw-r--r--pkg/bindings/manifests/types.go22
-rw-r--r--pkg/bindings/manifests/types_modify_options.go8
-rw-r--r--pkg/bindings/play/play.go1
-rw-r--r--pkg/bindings/system/system.go6
-rw-r--r--pkg/bindings/test/common_test.go3
-rw-r--r--pkg/bindings/test/manifests_test.go13
25 files changed, 218 insertions, 83 deletions
diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go
index 3739ec404..7dda955a2 100644
--- a/pkg/bindings/connection.go
+++ b/pkg/bindings/connection.go
@@ -2,6 +2,7 @@ package bindings
import (
"context"
+ "errors"
"fmt"
"io"
"net"
@@ -15,7 +16,6 @@ import (
"github.com/blang/semver"
"github.com/containers/podman/v4/pkg/terminal"
"github.com/containers/podman/v4/version"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
@@ -43,7 +43,7 @@ func GetClient(ctx context.Context) (*Connection, error) {
if c, ok := ctx.Value(clientKey).(*Connection); ok {
return c, nil
}
- return nil, errors.Errorf("%s not set in context", clientKey)
+ return nil, fmt.Errorf("%s not set in context", clientKey)
}
// ServiceVersion from context build by NewConnection()
@@ -92,10 +92,10 @@ func NewConnectionWithIdentity(ctx context.Context, uri string, identity string)
_url, err := url.Parse(uri)
if err != nil {
- return nil, errors.Wrapf(err, "Value of CONTAINER_HOST is not a valid url: %s", uri)
+ return nil, fmt.Errorf("value of CONTAINER_HOST is not a valid url: %s: %w", uri, err)
}
- // Now we setup the http Client to use the connection above
+ // Now we set up the http Client to use the connection above
var connection Connection
switch _url.Scheme {
case "ssh":
@@ -117,16 +117,16 @@ func NewConnectionWithIdentity(ctx context.Context, uri string, identity string)
}
connection = tcpClient(_url)
default:
- return nil, errors.Errorf("unable to create connection. %q is not a supported schema", _url.Scheme)
+ return nil, fmt.Errorf("unable to create connection. %q is not a supported schema", _url.Scheme)
}
if err != nil {
- return nil, errors.Wrapf(err, "unable to connect to Podman. failed to create %sClient", _url.Scheme)
+ return nil, fmt.Errorf("unable to connect to Podman. failed to create %sClient: %w", _url.Scheme, err)
}
ctx = context.WithValue(ctx, clientKey, &connection)
serviceVersion, err := pingNewConnection(ctx)
if err != nil {
- return nil, errors.Wrap(err, "unable to connect to Podman socket")
+ return nil, fmt.Errorf("unable to connect to Podman socket: %w", err)
}
ctx = context.WithValue(ctx, versionKey, serviceVersion)
return ctx, nil
@@ -164,7 +164,7 @@ func pingNewConnection(ctx context.Context) (*semver.Version, error) {
if response.StatusCode == http.StatusOK {
versionHdr := response.Header.Get("Libpod-API-Version")
if versionHdr == "" {
- logrus.Info("Service did not provide Libpod-API-Version Header")
+ logrus.Warn("Service did not provide Libpod-API-Version Header")
return new(semver.Version), nil
}
versionSrv, err := semver.ParseTolerant(versionHdr)
@@ -177,11 +177,11 @@ func pingNewConnection(ctx context.Context) (*semver.Version, error) {
// Server's job when Client version is equal or older
return &versionSrv, nil
case 1:
- return nil, errors.Errorf("server API version is too old. Client %q server %q",
+ return nil, fmt.Errorf("server API version is too old. Client %q server %q",
version.APIVersion[version.Libpod][version.MinimalAPI].String(), versionSrv.String())
}
}
- return nil, errors.Errorf("ping response was %d", response.StatusCode)
+ return nil, fmt.Errorf("ping response was %d", response.StatusCode)
}
func sshClient(_url *url.URL, secure bool, passPhrase string, identity string) (Connection, error) {
@@ -193,7 +193,7 @@ func sshClient(_url *url.URL, secure bool, passPhrase string, identity string) (
if len(identity) > 0 {
s, err := terminal.PublicKey(identity, []byte(passPhrase))
if err != nil {
- return Connection{}, errors.Wrapf(err, "failed to parse identity %q", identity)
+ return Connection{}, fmt.Errorf("failed to parse identity %q: %w", identity, err)
}
signers = append(signers, s)
@@ -289,7 +289,7 @@ func sshClient(_url *url.URL, secure bool, passPhrase string, identity string) (
},
)
if err != nil {
- return Connection{}, errors.Wrapf(err, "connection to bastion host (%s) failed", _url.String())
+ return Connection{}, fmt.Errorf("connection to bastion host (%s) failed: %w", _url.String(), err)
}
connection := Connection{URI: _url}
@@ -315,7 +315,8 @@ func unixClient(_url *url.URL) Connection {
return connection
}
-// DoRequest assembles the http request and returns the response
+// DoRequest assembles the http request and returns the response.
+// The caller must close the response body.
func (c *Connection) DoRequest(ctx context.Context, httpBody io.Reader, httpMethod, endpoint string, queryParams url.Values, headers http.Header, pathValues ...string) (*APIResponse, error) {
var (
err error
@@ -361,7 +362,7 @@ func (c *Connection) DoRequest(ctx context.Context, httpBody io.Reader, httpMeth
// Give the Do three chances in the case of a comm/service hiccup
for i := 1; i <= 3; i++ {
- response, err = c.Client.Do(req) // nolint
+ response, err = c.Client.Do(req) //nolint:bodyclose // The caller has to close the body.
if err == nil {
break
}
@@ -378,7 +379,7 @@ func (c *Connection) GetDialer(ctx context.Context) (net.Conn, error) {
return transport.DialContext(ctx, c.URI.Scheme, c.URI.String())
}
- return nil, errors.New("Unable to get dial context")
+ return nil, errors.New("unable to get dial context")
}
// IsInformational returns true if the response code is 1xx
diff --git a/pkg/bindings/containers/archive.go b/pkg/bindings/containers/archive.go
index 4f4b5a36a..660d9da6b 100644
--- a/pkg/bindings/containers/archive.go
+++ b/pkg/bindings/containers/archive.go
@@ -2,6 +2,7 @@ package containers
import (
"context"
+ "errors"
"io"
"net/http"
"net/url"
@@ -9,7 +10,6 @@ import (
"github.com/containers/podman/v4/pkg/bindings"
"github.com/containers/podman/v4/pkg/copy"
"github.com/containers/podman/v4/pkg/domain/entities"
- "github.com/pkg/errors"
)
// Stat checks if the specified path is on the container. Note that the stat
@@ -55,8 +55,6 @@ func CopyFromArchive(ctx context.Context, nameOrID string, path string, reader i
}
// CopyFromArchiveWithOptions copy files into container
-//
-// FIXME: remove this function and make CopyFromArchive accept the option as the last parameter in podman 4.0
func CopyFromArchiveWithOptions(ctx context.Context, nameOrID string, path string, reader io.Reader, options *CopyOptions) (entities.ContainerCopyFunc, error) {
conn, err := bindings.GetClient(ctx)
if err != nil {
diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go
index d84b47052..e23ee5ee9 100644
--- a/pkg/bindings/containers/attach.go
+++ b/pkg/bindings/containers/attach.go
@@ -4,6 +4,7 @@ import (
"bytes"
"context"
"encoding/binary"
+ "errors"
"fmt"
"io"
"net"
@@ -14,11 +15,10 @@ import (
"strconv"
"time"
+ "github.com/containers/common/pkg/util"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/bindings"
- "github.com/containers/podman/v4/utils"
"github.com/moby/term"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
terminal "golang.org/x/term"
)
@@ -54,8 +54,6 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri
stderr = (io.Writer)(nil)
}
- logrus.Infof("Going to attach to container %q", nameOrID)
-
conn, err := bindings.GetClient(ctx)
if err != nil {
return err
@@ -77,7 +75,7 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri
detachKeysInBytes, err = term.ToBytes(options.GetDetachKeys())
if err != nil {
- return errors.Wrapf(err, "invalid detach keys")
+ return fmt.Errorf("invalid detach keys: %w", err)
}
}
if isSet.stdin {
@@ -161,7 +159,7 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri
go func() {
logrus.Debugf("Copying STDIN to socket")
- _, err := utils.CopyDetachable(socket, stdin, detachKeysInBytes)
+ _, err := util.CopyDetachable(socket, stdin, detachKeysInBytes)
if err != nil && err != define.ErrDetach {
logrus.Errorf("Failed to write input to service: %v", err)
}
@@ -263,7 +261,7 @@ func DemuxHeader(r io.Reader, buffer []byte) (fd, sz int, err error) {
fd = int(buffer[0])
if fd < 0 || fd > 3 {
- err = errors.Wrapf(ErrLostSync, fmt.Sprintf(`channel "%d" found, 0-3 supported`, fd))
+ err = fmt.Errorf(`channel "%d" found, 0-3 supported: %w`, fd, ErrLostSync)
return
}
@@ -357,7 +355,7 @@ func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, i
resizeErr = ResizeContainerTTY(ctx, id, new(ResizeTTYOptions).WithHeight(h).WithWidth(w))
}
if resizeErr != nil {
- logrus.Infof("Failed to resize TTY: %v", resizeErr)
+ logrus.Debugf("Failed to resize TTY: %v", resizeErr)
}
}
@@ -499,7 +497,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar
if options.GetAttachInput() {
go func() {
logrus.Debugf("Copying STDIN to socket")
- _, err := utils.CopyDetachable(socket, options.InputStream, []byte{})
+ _, err := util.CopyDetachable(socket, options.InputStream, []byte{})
if err != nil {
logrus.Errorf("Failed to write input to service: %v", err)
}
@@ -520,7 +518,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar
return fmt.Errorf("exec session %s has a terminal and must have STDOUT enabled", sessionID)
}
// If not multiplex'ed, read from server and write to stdout
- _, err := utils.CopyDetachable(options.GetOutputStream(), socket, []byte{})
+ _, err := util.CopyDetachable(options.GetOutputStream(), socket, []byte{})
if err != nil {
return err
}
diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go
index be421cc8b..80ec7bc6f 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -2,6 +2,8 @@ package containers
import (
"context"
+ "errors"
+ "fmt"
"io"
"net/http"
"net/url"
@@ -12,8 +14,6 @@ import (
"github.com/containers/podman/v4/pkg/bindings"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/domain/entities/reports"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
)
var (
@@ -25,7 +25,7 @@ var (
// the most recent number of containers. The pod and size booleans indicate that pod information and rootfs
// size information should also be included. Finally, the sync bool synchronizes the OCI runtime and
// container state.
-func List(ctx context.Context, options *ListOptions) ([]entities.ListContainer, error) { // nolint:typecheck
+func List(ctx context.Context, options *ListOptions) ([]entities.ListContainer, error) {
if options == nil {
options = new(ListOptions)
}
@@ -201,7 +201,6 @@ func Start(ctx context.Context, nameOrID string, options *StartOptions) error {
if options == nil {
options = new(StartOptions)
}
- logrus.Infof("Going to start container %q", nameOrID)
conn, err := bindings.GetClient(ctx)
if err != nil {
return err
@@ -339,7 +338,7 @@ func Unpause(ctx context.Context, nameOrID string, options *UnpauseOptions) erro
// Wait blocks until the given container reaches a condition. If not provided, the condition will
// default to stopped. If the condition is stopped, an exit code for the container will be provided. The
// nameOrID can be a container name or a partial/full ID.
-func Wait(ctx context.Context, nameOrID string, options *WaitOptions) (int32, error) { // nolint
+func Wait(ctx context.Context, nameOrID string, options *WaitOptions) (int32, error) {
if options == nil {
options = new(WaitOptions)
}
@@ -449,7 +448,7 @@ func ContainerInit(ctx context.Context, nameOrID string, options *InitOptions) e
defer response.Body.Close()
if response.StatusCode == http.StatusNotModified {
- return errors.Wrapf(define.ErrCtrStateInvalid, "container %s has already been created in runtime", nameOrID)
+ return fmt.Errorf("container %s has already been created in runtime: %w", nameOrID, define.ErrCtrStateInvalid)
}
return response.Process(nil)
}
diff --git a/pkg/bindings/containers/exec.go b/pkg/bindings/containers/exec.go
index 3ad5d67d2..3d19fb812 100644
--- a/pkg/bindings/containers/exec.go
+++ b/pkg/bindings/containers/exec.go
@@ -3,6 +3,8 @@ package containers
import (
"bytes"
"context"
+ "errors"
+ "fmt"
"net/http"
"strings"
@@ -11,7 +13,6 @@ import (
"github.com/containers/podman/v4/pkg/bindings"
"github.com/containers/podman/v4/pkg/domain/entities"
jsoniter "github.com/json-iterator/go"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -27,12 +28,12 @@ func ExecCreate(ctx context.Context, nameOrID string, config *handlers.ExecCreat
}
if config == nil {
- return "", errors.Errorf("must provide a configuration for exec session")
+ return "", errors.New("must provide a configuration for exec session")
}
requestJSON, err := json.Marshal(config)
if err != nil {
- return "", errors.Wrapf(err, "error marshalling exec config to JSON")
+ return "", fmt.Errorf("error marshalling exec config to JSON: %w", err)
}
jsonReader := strings.NewReader(string(requestJSON))
diff --git a/pkg/bindings/containers/logs.go b/pkg/bindings/containers/logs.go
index 8ea8ed7fa..9ebfd90da 100644
--- a/pkg/bindings/containers/logs.go
+++ b/pkg/bindings/containers/logs.go
@@ -2,13 +2,13 @@ package containers
import (
"context"
+ "errors"
"fmt"
"io"
"net/http"
"strconv"
"github.com/containers/podman/v4/pkg/bindings"
- "github.com/pkg/errors"
)
// Logs obtains a container's logs given the options provided. The logs are then sent to the
diff --git a/pkg/bindings/containers/types.go b/pkg/bindings/containers/types.go
index 81d491bb7..f640ba756 100644
--- a/pkg/bindings/containers/types.go
+++ b/pkg/bindings/containers/types.go
@@ -287,4 +287,7 @@ type CopyOptions struct {
Chown *bool `schema:"copyUIDGID"`
// Map to translate path names.
Rename map[string]string
+ // NoOverwriteDirNonDir when true prevents an existing directory or file from being overwritten
+ // by the other type.
+ NoOverwriteDirNonDir *bool
}
diff --git a/pkg/bindings/containers/types_copy_options.go b/pkg/bindings/containers/types_copy_options.go
index 8fcfe71a6..e43d79752 100644
--- a/pkg/bindings/containers/types_copy_options.go
+++ b/pkg/bindings/containers/types_copy_options.go
@@ -46,3 +46,18 @@ func (o *CopyOptions) GetRename() map[string]string {
}
return o.Rename
}
+
+// WithNoOverwriteDirNonDir set field NoOverwriteDirNonDir to given value
+func (o *CopyOptions) WithNoOverwriteDirNonDir(value bool) *CopyOptions {
+ o.NoOverwriteDirNonDir = &value
+ return o
+}
+
+// GetNoOverwriteDirNonDir returns value of field NoOverwriteDirNonDir
+func (o *CopyOptions) GetNoOverwriteDirNonDir() bool {
+ if o.NoOverwriteDirNonDir == nil {
+ var z bool
+ return z
+ }
+ return *o.NoOverwriteDirNonDir
+}
diff --git a/pkg/bindings/errors.go b/pkg/bindings/errors.go
index eb95764ba..29f087c22 100644
--- a/pkg/bindings/errors.go
+++ b/pkg/bindings/errors.go
@@ -2,10 +2,11 @@ package bindings
import (
"encoding/json"
+ "errors"
+ "fmt"
"io/ioutil"
"github.com/containers/podman/v4/pkg/errorhandling"
- "github.com/pkg/errors"
)
var (
@@ -30,7 +31,7 @@ func (h APIResponse) Process(unmarshalInto interface{}) error {
func (h APIResponse) ProcessWithError(unmarshalInto interface{}, unmarshalErrorInto interface{}) error {
data, err := ioutil.ReadAll(h.Response.Body)
if err != nil {
- return errors.Wrap(err, "unable to process API response")
+ return fmt.Errorf("unable to process API response: %w", err)
}
if h.IsSuccess() || h.IsRedirection() {
if unmarshalInto != nil {
diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go
index 51dcd2aa5..6883585e2 100644
--- a/pkg/bindings/images/build.go
+++ b/pkg/bindings/images/build.go
@@ -5,6 +5,7 @@ import (
"compress/gzip"
"context"
"encoding/json"
+ "errors"
"fmt"
"io"
"io/fs"
@@ -28,7 +29,6 @@ import (
"github.com/docker/go-units"
"github.com/hashicorp/go-multierror"
jsoniter "github.com/json-iterator/go"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -65,6 +65,14 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
params.Set("annotations", l)
}
+ if cppflags := options.CPPFlags; len(cppflags) > 0 {
+ l, err := jsoniter.MarshalToString(cppflags)
+ if err != nil {
+ return nil, err
+ }
+ params.Set("cppflags", l)
+ }
+
if options.AllPlatforms {
params.Add("allplatforms", "1")
}
@@ -73,6 +81,13 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
for _, tag := range options.AdditionalTags {
params.Add("t", tag)
}
+ if additionalBuildContexts := options.AdditionalBuildContexts; len(additionalBuildContexts) > 0 {
+ additionalBuildContextMap, err := jsoniter.Marshal(additionalBuildContexts)
+ if err != nil {
+ return nil, err
+ }
+ params.Set("additionalbuildcontexts", string(additionalBuildContextMap))
+ }
if buildArgs := options.Args; len(buildArgs) > 0 {
bArgs, err := jsoniter.MarshalToString(buildArgs)
if err != nil {
@@ -155,6 +170,11 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
} else {
params.Set("rm", "0")
}
+ if options.CommonBuildOpts.OmitHistory {
+ params.Set("omithistory", "1")
+ } else {
+ params.Set("omithistory", "0")
+ }
if len(options.From) > 0 {
params.Set("from", options.From)
}
@@ -523,14 +543,14 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
if err := dec.Decode(&s); err != nil {
if errors.Is(err, io.ErrUnexpectedEOF) {
- return nil, errors.Wrap(err, "server probably quit")
+ return nil, fmt.Errorf("server probably quit: %w", err)
}
// EOF means the stream is over in which case we need
// to have read the id.
if errors.Is(err, io.EOF) && id != "" {
break
}
- return &entities.BuildReport{ID: id}, errors.Wrap(err, "decoding stream")
+ return &entities.BuildReport{ID: id}, fmt.Errorf("decoding stream: %w", err)
}
switch {
@@ -554,11 +574,11 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
func nTar(excludes []string, sources ...string) (io.ReadCloser, error) {
pm, err := fileutils.NewPatternMatcher(excludes)
if err != nil {
- return nil, errors.Wrapf(err, "error processing excludes list %v", excludes)
+ return nil, fmt.Errorf("error processing excludes list %v: %w", excludes, err)
}
if len(sources) == 0 {
- return nil, errors.New("No source(s) provided for build")
+ return nil, errors.New("no source(s) provided for build")
}
pr, pw := io.Pipe()
@@ -601,9 +621,9 @@ func nTar(excludes []string, sources ...string) (io.ReadCloser, error) {
}
name := filepath.ToSlash(strings.TrimPrefix(path, s+string(filepath.Separator)))
- excluded, err := pm.Matches(name) // nolint:staticcheck
+ excluded, err := pm.Matches(name) //nolint:staticcheck
if err != nil {
- return errors.Wrapf(err, "error checking if %q is excluded", name)
+ return fmt.Errorf("error checking if %q is excluded: %w", name, err)
}
if excluded {
// Note: filepath.SkipDir is not possible to use given .dockerignore semantics.
@@ -706,7 +726,7 @@ func parseDockerignore(root string) ([]string, error) {
var dockerIgnoreErr error
ignore, dockerIgnoreErr = ioutil.ReadFile(filepath.Join(root, ".dockerignore"))
if dockerIgnoreErr != nil && !os.IsNotExist(dockerIgnoreErr) {
- return nil, errors.Wrapf(err, "error reading .containerignore: '%s'", root)
+ return nil, fmt.Errorf("error reading .containerignore: '%s': %w", root, err)
}
}
rawexcludes := strings.Split(string(ignore), "\n")
diff --git a/pkg/bindings/images/build_unix.go b/pkg/bindings/images/build_unix.go
index 32e2ba9af..07bb8cbcd 100644
--- a/pkg/bindings/images/build_unix.go
+++ b/pkg/bindings/images/build_unix.go
@@ -11,7 +11,7 @@ import (
func checkHardLink(fi os.FileInfo) (devino, bool) {
st := fi.Sys().(*syscall.Stat_t)
return devino{
- Dev: uint64(st.Dev), // nolint: unconvert
+ Dev: uint64(st.Dev), //nolint: unconvert
Ino: st.Ino,
}, st.Nlink > 1
}
diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go
index 8e3b07929..cd5147629 100644
--- a/pkg/bindings/images/images.go
+++ b/pkg/bindings/images/images.go
@@ -2,6 +2,7 @@ package images
import (
"context"
+ "errors"
"fmt"
"io"
"net/http"
@@ -14,7 +15,6 @@ import (
"github.com/containers/podman/v4/pkg/bindings"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/domain/entities/reports"
- "github.com/pkg/errors"
)
// Exists a lightweight way to determine if an image exists in local storage. It returns a
@@ -280,7 +280,6 @@ func Push(ctx context.Context, source string, destination string, options *PushO
if err != nil {
return err
}
- // TODO: have a global system context we can pass around (1st argument)
header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword())
if err != nil {
return err
@@ -329,7 +328,6 @@ func Search(ctx context.Context, term string, options *SearchOptions) ([]entitie
params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify()))
}
- // TODO: have a global system context we can pass around (1st argument)
header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, "", "")
if err != nil {
return nil, err
@@ -348,3 +346,23 @@ func Search(ctx context.Context, term string, options *SearchOptions) ([]entitie
return results, nil
}
+
+func Scp(ctx context.Context, source, destination *string, options ScpOptions) (reports.ScpReport, error) {
+ rep := reports.ScpReport{}
+
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return rep, err
+ }
+ params, err := options.ToParams()
+ if err != nil {
+ return rep, err
+ }
+ response, err := conn.DoRequest(ctx, nil, http.MethodPost, fmt.Sprintf("/images/scp/%s", *source), params, nil)
+ if err != nil {
+ return rep, err
+ }
+ defer response.Body.Close()
+
+ return rep, response.Process(&rep)
+}
diff --git a/pkg/bindings/images/pull.go b/pkg/bindings/images/pull.go
index 20e47179c..1a4aa3038 100644
--- a/pkg/bindings/images/pull.go
+++ b/pkg/bindings/images/pull.go
@@ -3,6 +3,7 @@ package images
import (
"context"
"encoding/json"
+ "errors"
"fmt"
"io"
"io/ioutil"
@@ -15,7 +16,6 @@ import (
"github.com/containers/podman/v4/pkg/bindings"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/errorhandling"
- "github.com/pkg/errors"
)
// Pull is the binding for libpod's v2 endpoints for pulling images. Note that
@@ -42,7 +42,6 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string,
params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify()))
}
- // TODO: have a global system context we can pass around (1st argument)
header, err := auth.MakeXRegistryAuthHeader(&types.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword())
if err != nil {
return nil, err
@@ -92,7 +91,7 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string,
images = report.Images
case report.ID != "":
default:
- return images, errors.Errorf("failed to parse pull results stream, unexpected input: %v", report)
+ return images, fmt.Errorf("failed to parse pull results stream, unexpected input: %v", report)
}
}
return images, errorhandling.JoinErrors(pullErrors)
diff --git a/pkg/bindings/images/rm.go b/pkg/bindings/images/rm.go
index b80bacf45..eb3eef10c 100644
--- a/pkg/bindings/images/rm.go
+++ b/pkg/bindings/images/rm.go
@@ -16,9 +16,6 @@ func Remove(ctx context.Context, images []string, options *RemoveOptions) (*enti
if options == nil {
options = new(RemoveOptions)
}
- // FIXME - bindings tests are missing for this endpoint. Once the CI is
- // re-enabled for bindings, we need to add them. At the time of writing,
- // the tests don't compile.
var report types.LibpodImagesRemoveReport
conn, err := bindings.GetClient(ctx)
if err != nil {
diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go
index 8e5e7ee92..3728ae5c0 100644
--- a/pkg/bindings/images/types.go
+++ b/pkg/bindings/images/types.go
@@ -13,6 +13,8 @@ type RemoveOptions struct {
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
}
//go:generate go run ../generator/generator.go DiffOptions
@@ -127,6 +129,8 @@ type PushOptions struct {
Password *string
// SkipTLSVerify to skip HTTPS and certificate verification.
SkipTLSVerify *bool
+ // RemoveSignatures Discard any pre-existing signatures in the image.
+ RemoveSignatures *bool
// Username for authenticating against the registry.
Username *string
}
@@ -186,3 +190,8 @@ type BuildOptions struct {
// ExistsOptions are optional options for checking if an image exists
type ExistsOptions struct {
}
+
+type ScpOptions struct {
+ Quiet *bool
+ Destination *string
+}
diff --git a/pkg/bindings/images/types_push_options.go b/pkg/bindings/images/types_push_options.go
index 4985c9451..25f6c5546 100644
--- a/pkg/bindings/images/types_push_options.go
+++ b/pkg/bindings/images/types_push_options.go
@@ -107,6 +107,21 @@ func (o *PushOptions) GetSkipTLSVerify() bool {
return *o.SkipTLSVerify
}
+// WithRemoveSignatures set field RemoveSignatures to given value
+func (o *PushOptions) WithRemoveSignatures(value bool) *PushOptions {
+ o.RemoveSignatures = &value
+ return o
+}
+
+// GetRemoveSignatures returns value of field RemoveSignatures
+func (o *PushOptions) GetRemoveSignatures() bool {
+ if o.RemoveSignatures == nil {
+ var z bool
+ return z
+ }
+ return *o.RemoveSignatures
+}
+
// WithUsername set field Username to given value
func (o *PushOptions) WithUsername(value string) *PushOptions {
o.Username = &value
diff --git a/pkg/bindings/images/types_remove_options.go b/pkg/bindings/images/types_remove_options.go
index 613a33183..559ebcfd5 100644
--- a/pkg/bindings/images/types_remove_options.go
+++ b/pkg/bindings/images/types_remove_options.go
@@ -61,3 +61,18 @@ func (o *RemoveOptions) GetIgnore() bool {
}
return *o.Ignore
}
+
+// WithLookupManifest set field LookupManifest to given value
+func (o *RemoveOptions) WithLookupManifest(value bool) *RemoveOptions {
+ o.LookupManifest = &value
+ return o
+}
+
+// GetLookupManifest returns value of field LookupManifest
+func (o *RemoveOptions) GetLookupManifest() bool {
+ if o.LookupManifest == nil {
+ var z bool
+ return z
+ }
+ return *o.LookupManifest
+}
diff --git a/pkg/bindings/images/types_scp_options.go b/pkg/bindings/images/types_scp_options.go
new file mode 100644
index 000000000..5a1178cb1
--- /dev/null
+++ b/pkg/bindings/images/types_scp_options.go
@@ -0,0 +1,12 @@
+package images
+
+import (
+ "net/url"
+
+ "github.com/containers/podman/v4/pkg/bindings/internal/util"
+)
+
+// ToParams formats struct fields to be passed to API service
+func (o *ScpOptions) ToParams() (url.Values, error) {
+ return util.ToParams(o)
+}
diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go
index feff5d6e8..80153c4b4 100644
--- a/pkg/bindings/manifests/manifests.go
+++ b/pkg/bindings/manifests/manifests.go
@@ -2,6 +2,8 @@ package manifests
import (
"context"
+ "errors"
+ "fmt"
"io/ioutil"
"net/http"
"strconv"
@@ -15,7 +17,6 @@ import (
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/errorhandling"
jsoniter "github.com/json-iterator/go"
- "github.com/pkg/errors"
)
// Create creates a manifest for the given name. Optional images to be associated with
@@ -117,6 +118,26 @@ func Remove(ctx context.Context, name, digest string, _ *RemoveOptions) (string,
return Modify(ctx, name, []string{digest}, optionsv4)
}
+// Delete removes specified manifest from local storage.
+func Delete(ctx context.Context, name string) (*entities.ManifestRemoveReport, error) {
+ var report entities.ManifestRemoveReport
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+ response, err := conn.DoRequest(ctx, nil, http.MethodDelete, "/manifests/%s", nil, nil, name)
+ if err != nil {
+ return nil, err
+ }
+ defer response.Body.Close()
+
+ if err := response.Process(&report); err != nil {
+ return nil, err
+ }
+
+ return &report, errorhandling.JoinErrors(errorhandling.StringsToErrors(report.Errors))
+}
+
// 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.
@@ -199,19 +220,19 @@ func Modify(ctx context.Context, name string, images []string, options *ModifyOp
data, err := ioutil.ReadAll(response.Body)
if err != nil {
- return "", errors.Wrap(err, "unable to process API response")
+ return "", fmt.Errorf("unable to process API response: %w", err)
}
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")
+ return "", fmt.Errorf("unable to decode API response: %w", err)
}
err = errorhandling.JoinErrors(report.Errors)
if err != nil {
errModel := errorhandling.ErrorModel{
- Because: (errors.Cause(err)).Error(),
+ Because: errorhandling.Cause(err).Error(),
Message: err.Error(),
ResponseCode: response.StatusCode,
}
@@ -224,7 +245,7 @@ func Modify(ctx context.Context, name string, images []string, options *ModifyOp
ResponseCode: response.StatusCode,
}
if err = jsoniter.Unmarshal(data, &errModel); err != nil {
- return "", errors.Wrap(err, "unable to decode API response")
+ return "", fmt.Errorf("unable to decode API response: %w", err)
}
return "", &errModel
}
diff --git a/pkg/bindings/manifests/types.go b/pkg/bindings/manifests/types.go
index d0b0b2e71..e23ef798d 100644
--- a/pkg/bindings/manifests/types.go
+++ b/pkg/bindings/manifests/types.go
@@ -44,16 +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
+ // OS features for the image
+ OSFeatures []string `json:"os_features" schema:"os_features"`
+ // OSVersion overrides the operating system for the image
+ OSVersion *string `json:"os_version" schema:"os_version"`
+ Variant *string // Variant overrides the operating system variant for the image
Authfile *string
Password *string
Username *string
diff --git a/pkg/bindings/manifests/types_modify_options.go b/pkg/bindings/manifests/types_modify_options.go
index 9d2ed2613..ab00cb2c5 100644
--- a/pkg/bindings/manifests/types_modify_options.go
+++ b/pkg/bindings/manifests/types_modify_options.go
@@ -122,13 +122,13 @@ func (o *ModifyOptions) GetOS() string {
return *o.OS
}
-// WithOSFeatures set oS features for the image
+// WithOSFeatures set field OSFeatures to given value
func (o *ModifyOptions) WithOSFeatures(value []string) *ModifyOptions {
o.OSFeatures = value
return o
}
-// GetOSFeatures returns value of oS features for the image
+// GetOSFeatures returns value of field OSFeatures
func (o *ModifyOptions) GetOSFeatures() []string {
if o.OSFeatures == nil {
var z []string
@@ -137,13 +137,13 @@ func (o *ModifyOptions) GetOSFeatures() []string {
return o.OSFeatures
}
-// WithOSVersion set oSVersion overrides the operating system for the image
+// WithOSVersion set field OSVersion to given value
func (o *ModifyOptions) WithOSVersion(value string) *ModifyOptions {
o.OSVersion = &value
return o
}
-// GetOSVersion returns value of oSVersion overrides the operating system for the image
+// GetOSVersion returns value of field OSVersion
func (o *ModifyOptions) GetOSVersion() string {
if o.OSVersion == nil {
var z string
diff --git a/pkg/bindings/play/play.go b/pkg/bindings/play/play.go
index 8058a8514..0261b0250 100644
--- a/pkg/bindings/play/play.go
+++ b/pkg/bindings/play/play.go
@@ -46,7 +46,6 @@ func KubeWithBody(ctx context.Context, body io.Reader, options *KubeOptions) (*e
params.Set("start", strconv.FormatBool(options.GetStart()))
}
- // TODO: have a global system context we can pass around (1st argument)
header, err := auth.MakeXRegistryAuthHeader(&types.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword())
if err != nil {
return nil, err
diff --git a/pkg/bindings/system/system.go b/pkg/bindings/system/system.go
index 5ef78e444..dae80384b 100644
--- a/pkg/bindings/system/system.go
+++ b/pkg/bindings/system/system.go
@@ -3,6 +3,7 @@ package system
import (
"context"
"encoding/json"
+ "errors"
"fmt"
"io"
"net/http"
@@ -11,7 +12,6 @@ import (
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/bindings"
"github.com/containers/podman/v4/pkg/domain/entities"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -37,7 +37,7 @@ func Events(ctx context.Context, eventChan chan entities.Event, cancelChan chan
go func() {
<-cancelChan
err = response.Body.Close()
- logrus.Error(errors.Wrap(err, "unable to close event response body"))
+ logrus.Errorf("Unable to close event response body: %v", err)
}()
}
@@ -56,7 +56,7 @@ func Events(ctx context.Context, eventChan chan entities.Event, cancelChan chan
case errors.Is(err, io.EOF):
return nil
default:
- return errors.Wrap(err, "unable to decode event response")
+ return fmt.Errorf("unable to decode event response: %w", err)
}
}
diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go
index 950fd21e6..6b0175f59 100644
--- a/pkg/bindings/test/common_test.go
+++ b/pkg/bindings/test/common_test.go
@@ -16,7 +16,6 @@ import (
"github.com/containers/podman/v4/pkg/specgen"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega/gexec"
- "github.com/pkg/errors"
)
type testImage struct {
@@ -127,7 +126,7 @@ func (b *bindingTest) runPodman(command []string) *gexec.Session {
fmt.Printf("Running: %s %s\n", podmanBinary, strings.Join(cmd, " "))
session, err := gexec.Start(c, ginkgo.GinkgoWriter, ginkgo.GinkgoWriter)
if err != nil {
- panic(errors.Errorf("unable to run podman command: %q", cmd))
+ panic(fmt.Errorf("unable to run podman command: %q", cmd))
}
return session
}
diff --git a/pkg/bindings/test/manifests_test.go b/pkg/bindings/test/manifests_test.go
index e6c93817d..6a34ef5a6 100644
--- a/pkg/bindings/test/manifests_test.go
+++ b/pkg/bindings/test/manifests_test.go
@@ -62,6 +62,19 @@ var _ = Describe("podman manifest", func() {
Expect(len(list.Manifests)).To(BeNumerically("==", 1))
})
+ It("delete manifest", func() {
+ id, err := manifests.Create(bt.conn, "quay.io/libpod/foobar:latest", []string{}, nil)
+ Expect(err).ToNot(HaveOccurred(), err)
+ list, err := manifests.Inspect(bt.conn, id, nil)
+ Expect(err).ToNot(HaveOccurred())
+
+ Expect(len(list.Manifests)).To(BeZero())
+
+ removeReport, err := manifests.Delete(bt.conn, "quay.io/libpod/foobar:latest")
+ Expect(err).ToNot(HaveOccurred())
+ Expect(len(removeReport.Deleted)).To(BeNumerically("==", 1))
+ })
+
It("inspect", func() {
_, err := manifests.Inspect(bt.conn, "larry", nil)
Expect(err).To(HaveOccurred())