summaryrefslogtreecommitdiff
path: root/pkg/bindings
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/bindings')
-rw-r--r--pkg/bindings/bindings.go13
-rw-r--r--pkg/bindings/connection.go105
-rw-r--r--pkg/bindings/containers/checkpoint.go4
-rw-r--r--pkg/bindings/containers/commit.go2
-rw-r--r--pkg/bindings/containers/containers.go289
-rw-r--r--pkg/bindings/containers/create.go2
-rw-r--r--pkg/bindings/containers/diff.go2
-rw-r--r--pkg/bindings/containers/exec.go4
-rw-r--r--pkg/bindings/containers/healthcheck.go2
-rw-r--r--pkg/bindings/containers/logs.go78
-rw-r--r--pkg/bindings/containers/mount.go6
-rw-r--r--pkg/bindings/generate/generate.go32
-rw-r--r--pkg/bindings/images/diff.go2
-rw-r--r--pkg/bindings/images/images.go232
-rw-r--r--pkg/bindings/images/rm.go65
-rw-r--r--pkg/bindings/manifests/manifests.go36
-rw-r--r--pkg/bindings/network/network.go66
-rw-r--r--pkg/bindings/play/play.go49
-rw-r--r--pkg/bindings/pods/pods.go28
-rw-r--r--pkg/bindings/system/info.go2
-rw-r--r--pkg/bindings/system/system.go86
-rw-r--r--pkg/bindings/test/attach_test.go110
-rw-r--r--pkg/bindings/test/auth_test.go143
-rw-r--r--pkg/bindings/test/common_test.go2
-rw-r--r--pkg/bindings/test/containers_test.go213
-rw-r--r--pkg/bindings/test/exec_test.go4
-rw-r--r--pkg/bindings/test/images_test.go48
-rw-r--r--pkg/bindings/test/manifests_test.go24
-rw-r--r--pkg/bindings/test/pods_test.go16
-rw-r--r--pkg/bindings/test/system_test.go25
-rw-r--r--pkg/bindings/test/test_suite_test.go5
-rw-r--r--pkg/bindings/test/volumes_test.go2
-rw-r--r--pkg/bindings/version.go3
-rw-r--r--pkg/bindings/volumes/volumes.go10
34 files changed, 1396 insertions, 314 deletions
diff --git a/pkg/bindings/bindings.go b/pkg/bindings/bindings.go
index 4b07847d1..7e2a444bd 100644
--- a/pkg/bindings/bindings.go
+++ b/pkg/bindings/bindings.go
@@ -8,11 +8,20 @@
package bindings
+import (
+ "github.com/blang/semver"
+)
+
var (
// PTrue is a convenience variable that can be used in bindings where
// a pointer to a bool (optional parameter) is required.
- PTrue bool = true
+ pTrue = true
+ PTrue = &pTrue
// PFalse is a convenience variable that can be used in bindings where
// a pointer to a bool (optional parameter) is required.
- PFalse bool = false
+ pFalse = false
+ PFalse = &pFalse
+
+ // _*YES*- podman will fail to run if this value is wrong
+ APIVersion = semver.MustParse("1.0.0")
)
diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go
index da3755fc8..e9032f083 100644
--- a/pkg/bindings/connection.go
+++ b/pkg/bindings/connection.go
@@ -15,7 +15,7 @@ import (
"strings"
"time"
- "github.com/containers/libpod/pkg/api/types"
+ "github.com/blang/semver"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -27,7 +27,7 @@ var (
basePath = &url.URL{
Scheme: "http",
Host: "d",
- Path: "/v" + types.MinimalAPIVersion + "/libpod",
+ Path: "/v" + APIVersion.String() + "/libpod",
}
)
@@ -39,6 +39,7 @@ type APIResponse struct {
type Connection struct {
_url *url.URL
client *http.Client
+ conn *net.Conn
}
type valueKey string
@@ -88,26 +89,26 @@ func NewConnection(ctx context.Context, uri string, identity ...string) (context
}
// Now we setup the http client to use the connection above
- var client *http.Client
+ var connection Connection
switch _url.Scheme {
case "ssh":
secure, err = strconv.ParseBool(_url.Query().Get("secure"))
if err != nil {
secure = false
}
- client, err = sshClient(_url, identity[0], secure)
+ connection, err = sshClient(_url, identity[0], secure)
case "unix":
if !strings.HasPrefix(uri, "unix:///") {
// autofix unix://path_element vs unix:///path_element
_url.Path = JoinURL(_url.Host, _url.Path)
_url.Host = ""
}
- client, err = unixClient(_url)
+ connection, err = unixClient(_url)
case "tcp":
if !strings.HasPrefix(uri, "tcp://") {
return nil, errors.New("tcp URIs should begin with tcp://")
}
- client, err = tcpClient(_url)
+ connection, err = tcpClient(_url)
default:
return nil, errors.Errorf("'%s' is not a supported schema", _url.Scheme)
}
@@ -115,46 +116,71 @@ func NewConnection(ctx context.Context, uri string, identity ...string) (context
return nil, errors.Wrapf(err, "Failed to create %sClient", _url.Scheme)
}
- ctx = context.WithValue(ctx, clientKey, &Connection{_url, client})
+ ctx = context.WithValue(ctx, clientKey, &connection)
if err := pingNewConnection(ctx); err != nil {
return nil, err
}
return ctx, nil
}
-func tcpClient(_url *url.URL) (*http.Client, error) {
- return &http.Client{
+func tcpClient(_url *url.URL) (Connection, error) {
+ connection := Connection{
+ _url: _url,
+ }
+ connection.client = &http.Client{
Transport: &http.Transport{
- DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
- return net.Dial("tcp", _url.Host)
+ DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
+ conn, err := net.Dial("tcp", _url.Host)
+ if c, ok := ctx.Value(clientKey).(*Connection); ok {
+ c.conn = &conn
+ }
+ return conn, err
},
DisableCompression: true,
},
- }, nil
+ }
+ return connection, nil
}
// pingNewConnection pings to make sure the RESTFUL service is up
-// and running. it should only be used where initializing a connection
+// and running. it should only be used when initializing a connection
func pingNewConnection(ctx context.Context) error {
client, err := GetClient(ctx)
if err != nil {
return err
}
// the ping endpoint sits at / in this case
- response, err := client.DoRequest(nil, http.MethodGet, "../../../_ping", nil)
+ response, err := client.DoRequest(nil, http.MethodGet, "../../../_ping", nil, nil)
if err != nil {
return err
}
+
if response.StatusCode == http.StatusOK {
- return nil
+ versionHdr := response.Header.Get("Libpod-API-Version")
+ if versionHdr == "" {
+ logrus.Info("Service did not provide Libpod-API-Version Header")
+ return nil
+ }
+ versionSrv, err := semver.ParseTolerant(versionHdr)
+ if err != nil {
+ return err
+ }
+
+ switch APIVersion.Compare(versionSrv) {
+ case 1, 0:
+ // Server's job when client version is equal or older
+ return nil
+ case -1:
+ return errors.Errorf("server API version is too old. client %q server %q", APIVersion.String(), versionSrv.String())
+ }
}
return errors.Errorf("ping response was %q", response.StatusCode)
}
-func sshClient(_url *url.URL, identity string, secure bool) (*http.Client, error) {
+func sshClient(_url *url.URL, identity string, secure bool) (Connection, error) {
auth, err := publicKey(identity)
if err != nil {
- return nil, errors.Wrapf(err, "Failed to parse identity %s: %v\n", _url.String(), identity)
+ return Connection{}, errors.Wrapf(err, "Failed to parse identity %s: %v\n", _url.String(), identity)
}
callback := ssh.InsecureIgnoreHostKey()
@@ -188,30 +214,43 @@ func sshClient(_url *url.URL, identity string, secure bool) (*http.Client, error
},
)
if err != nil {
- return nil, errors.Wrapf(err, "Connection to bastion host (%s) failed.", _url.String())
+ return Connection{}, errors.Wrapf(err, "Connection to bastion host (%s) failed.", _url.String())
}
- return &http.Client{
+
+ connection := Connection{_url: _url}
+ connection.client = &http.Client{
Transport: &http.Transport{
- DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
- return bastion.Dial("unix", _url.Path)
+ DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
+ conn, err := bastion.Dial("unix", _url.Path)
+ if c, ok := ctx.Value(clientKey).(*Connection); ok {
+ c.conn = &conn
+ }
+ return conn, err
},
- }}, nil
+ }}
+ return connection, nil
}
-func unixClient(_url *url.URL) (*http.Client, error) {
- return &http.Client{
+func unixClient(_url *url.URL) (Connection, error) {
+ connection := Connection{_url: _url}
+ connection.client = &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
d := net.Dialer{}
- return d.DialContext(ctx, "unix", _url.Path)
+ conn, err := d.DialContext(ctx, "unix", _url.Path)
+ if c, ok := ctx.Value(clientKey).(*Connection); ok {
+ c.conn = &conn
+ }
+ return conn, err
},
DisableCompression: true,
},
- }, nil
+ }
+ return connection, nil
}
// DoRequest assembles the http request and returns the response
-func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string, queryParams url.Values, pathValues ...string) (*APIResponse, error) {
+func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string, queryParams url.Values, header map[string]string, pathValues ...string) (*APIResponse, error) {
var (
err error
response *http.Response
@@ -232,6 +271,10 @@ func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string,
if len(queryParams) > 0 {
req.URL.RawQuery = queryParams.Encode()
}
+ for key, val := range header {
+ req.Header.Set(key, val)
+ }
+ req = req.WithContext(context.WithValue(context.Background(), clientKey, c))
// Give the Do three chances in the case of a comm/service hiccup
for i := 0; i < 3; i++ {
response, err = c.client.Do(req) // nolint
@@ -243,6 +286,10 @@ func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string,
return &APIResponse{response, req}, err
}
+func (c *Connection) Write(b []byte) (int, error) {
+ return (*c.conn).Write(b)
+}
+
// FiltersToString converts our typical filter format of a
// map[string][]string to a query/html safe string.
func FiltersToString(filters map[string][]string) (string, error) {
@@ -295,8 +342,8 @@ func publicKey(path string) (ssh.AuthMethod, error) {
func hostKey(host string) ssh.PublicKey {
// parse OpenSSH known_hosts file
// ssh or use ssh-keyscan to get initial key
- known_hosts := filepath.Join(homedir.HomeDir(), ".ssh", "known_hosts")
- fd, err := os.Open(known_hosts)
+ knownHosts := filepath.Join(homedir.HomeDir(), ".ssh", "known_hosts")
+ fd, err := os.Open(knownHosts)
if err != nil {
logrus.Error(err)
return nil
diff --git a/pkg/bindings/containers/checkpoint.go b/pkg/bindings/containers/checkpoint.go
index 84924587b..f483a9297 100644
--- a/pkg/bindings/containers/checkpoint.go
+++ b/pkg/bindings/containers/checkpoint.go
@@ -34,7 +34,7 @@ func Checkpoint(ctx context.Context, nameOrId string, keep, leaveRunning, tcpEst
if export != nil {
params.Set("export", *export)
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/checkpoint", params, nameOrId)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/checkpoint", params, nil, nameOrId)
if err != nil {
return nil, err
}
@@ -71,7 +71,7 @@ func Restore(ctx context.Context, nameOrId string, keep, tcpEstablished, ignoreR
if importArchive != nil {
params.Set("import", *importArchive)
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/restore", params, nameOrId)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/restore", params, nil, nameOrId)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/containers/commit.go b/pkg/bindings/containers/commit.go
index 12c25f842..780d42272 100644
--- a/pkg/bindings/containers/commit.go
+++ b/pkg/bindings/containers/commit.go
@@ -41,7 +41,7 @@ func Commit(ctx context.Context, nameOrId string, options CommitOptions) (handle
if options.Tag != nil {
params.Set("tag", *options.Tag)
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/commit", params)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/commit", params, nil)
if err != nil {
return id, err
}
diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go
index e74a256c7..516f3d282 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -2,9 +2,14 @@ package containers
import (
"context"
+ "encoding/binary"
+ "fmt"
"io"
"net/http"
"net/url"
+ "os"
+ "os/signal"
+ "reflect"
"strconv"
"strings"
@@ -12,7 +17,14 @@ import (
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/domain/entities"
+ sig "github.com/containers/libpod/pkg/signal"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+var (
+ ErrLostSync = errors.New("lost synchronization with multiplexed stream")
)
// List obtains a list of containers in local storage. All parameters to this method are optional.
@@ -49,7 +61,7 @@ func List(ctx context.Context, filters map[string][]string, all *bool, last *int
}
params.Set("filters", filterString)
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/containers/json", params)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/containers/json", params, nil)
if err != nil {
return containers, err
}
@@ -74,7 +86,7 @@ func Prune(ctx context.Context, filters map[string][]string) (*entities.Containe
}
params.Set("filters", filterString)
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/prune", params)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/prune", params, nil)
if err != nil {
return nil, err
}
@@ -96,7 +108,7 @@ func Remove(ctx context.Context, nameOrID string, force, volumes *bool) error {
if volumes != nil {
params.Set("vols", strconv.FormatBool(*volumes))
}
- response, err := conn.DoRequest(nil, http.MethodDelete, "/containers/%s", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodDelete, "/containers/%s", params, nil, nameOrID)
if err != nil {
return err
}
@@ -116,7 +128,7 @@ func Inspect(ctx context.Context, nameOrID string, size *bool) (*define.InspectC
if size != nil {
params.Set("size", strconv.FormatBool(*size))
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/json", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/json", params, nil, nameOrID)
if err != nil {
return nil, err
}
@@ -134,7 +146,7 @@ func Kill(ctx context.Context, nameOrID string, sig string) error {
}
params := url.Values{}
params.Set("signal", sig)
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/kill", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/kill", params, nil, nameOrID)
if err != nil {
return err
}
@@ -149,7 +161,7 @@ func Pause(ctx context.Context, nameOrID string) error {
if err != nil {
return err
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/pause", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/pause", nil, nil, nameOrID)
if err != nil {
return err
}
@@ -168,7 +180,7 @@ func Restart(ctx context.Context, nameOrID string, timeout *int) error {
if timeout != nil {
params.Set("t", strconv.Itoa(*timeout))
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/restart", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/restart", params, nil, nameOrID)
if err != nil {
return err
}
@@ -187,7 +199,7 @@ func Start(ctx context.Context, nameOrID string, detachKeys *string) error {
if detachKeys != nil {
params.Set("detachKeys", *detachKeys)
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/start", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/start", params, nil, nameOrID)
if err != nil {
return err
}
@@ -209,7 +221,7 @@ func Top(ctx context.Context, nameOrID string, descriptors []string) ([]string,
// flatten the slice into one string
params.Set("ps_args", strings.Join(descriptors, ","))
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/top", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/top", params, nil, nameOrID)
if err != nil {
return nil, err
}
@@ -237,7 +249,7 @@ func Unpause(ctx context.Context, nameOrID string) error {
if err != nil {
return err
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/unpause", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/unpause", nil, nil, nameOrID)
if err != nil {
return err
}
@@ -247,7 +259,7 @@ func Unpause(ctx context.Context, nameOrID string) error {
// 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, condition *define.ContainerStatus) (int32, error) { //nolint
+func Wait(ctx context.Context, nameOrID string, condition *define.ContainerStatus) (int32, error) { // nolint
var exitCode int32
conn, err := bindings.GetClient(ctx)
if err != nil {
@@ -257,7 +269,7 @@ func Wait(ctx context.Context, nameOrID string, condition *define.ContainerStatu
if condition != nil {
params.Set("condition", condition.String())
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/wait", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/wait", params, nil, nameOrID)
if err != nil {
return exitCode, err
}
@@ -272,7 +284,7 @@ func Exists(ctx context.Context, nameOrID string) (bool, error) {
if err != nil {
return false, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/exists", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/exists", nil, nil, nameOrID)
if err != nil {
return false, err
}
@@ -290,7 +302,7 @@ func Stop(ctx context.Context, nameOrID string, timeout *uint) error {
if timeout != nil {
params.Set("t", strconv.Itoa(int(*timeout)))
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/stop", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/stop", params, nil, nameOrID)
if err != nil {
return err
}
@@ -305,7 +317,7 @@ func Export(ctx context.Context, nameOrID string, w io.Writer) error {
if err != nil {
return err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/export", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/export", params, nil, nameOrID)
if err != nil {
return err
}
@@ -324,7 +336,7 @@ func ContainerInit(ctx context.Context, nameOrID string) error {
if err != nil {
return err
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/init", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/init", nil, nil, nameOrID)
if err != nil {
return err
}
@@ -333,3 +345,248 @@ func ContainerInit(ctx context.Context, nameOrID string) error {
}
return response.Process(nil)
}
+
+// Attach attaches to a running container
+func Attach(ctx context.Context, nameOrId string, detachKeys *string, logs, stream *bool, stdin io.Reader, stdout io.Writer, stderr io.Writer, attachReady chan bool) error {
+ isSet := struct {
+ stdin bool
+ stdout bool
+ stderr bool
+ }{
+ stdin: !(stdin == nil || reflect.ValueOf(stdin).IsNil()),
+ stdout: !(stdout == nil || reflect.ValueOf(stdout).IsNil()),
+ stderr: !(stderr == nil || reflect.ValueOf(stderr).IsNil()),
+ }
+ // Ensure golang can determine that interfaces are "really" nil
+ if !isSet.stdin {
+ stdin = (io.Reader)(nil)
+ }
+ if !isSet.stdout {
+ stdout = (io.Writer)(nil)
+ }
+ if !isSet.stderr {
+ stderr = (io.Writer)(nil)
+ }
+
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return err
+ }
+
+ // Do we need to wire in stdin?
+ ctnr, err := Inspect(ctx, nameOrId, bindings.PFalse)
+ if err != nil {
+ return err
+ }
+
+ params := url.Values{}
+ if detachKeys != nil {
+ params.Add("detachKeys", *detachKeys)
+ }
+ if logs != nil {
+ params.Add("logs", fmt.Sprintf("%t", *logs))
+ }
+ if stream != nil {
+ params.Add("stream", fmt.Sprintf("%t", *stream))
+ }
+ if isSet.stdin {
+ params.Add("stdin", "true")
+ }
+ if isSet.stdout {
+ params.Add("stdout", "true")
+ }
+ if isSet.stderr {
+ params.Add("stderr", "true")
+ }
+
+ // Unless all requirements are met, don't use "stdin" is a terminal
+ file, ok := stdin.(*os.File)
+ needTTY := ok && terminal.IsTerminal(int(file.Fd())) && ctnr.Config.Tty
+ if needTTY {
+ state, err := terminal.MakeRaw(int(file.Fd()))
+ if err != nil {
+ return err
+ }
+
+ logrus.SetFormatter(&rawFormatter{})
+
+ defer func() {
+ if err := terminal.Restore(int(file.Fd()), state); err != nil {
+ logrus.Errorf("unable to restore terminal: %q", err)
+ }
+ logrus.SetFormatter(&logrus.TextFormatter{})
+ }()
+
+ winChange := make(chan os.Signal, 1)
+ signal.Notify(winChange, sig.SIGWINCH)
+ winCtx, winCancel := context.WithCancel(ctx)
+ defer winCancel()
+
+ go func() {
+ // Prime the pump, we need one reset to ensure everything is ready
+ winChange <- sig.SIGWINCH
+ for {
+ select {
+ case <-winCtx.Done():
+ return
+ case <-winChange:
+ h, w, err := terminal.GetSize(int(file.Fd()))
+ if err != nil {
+ logrus.Warnf("failed to obtain TTY size: " + err.Error())
+ }
+
+ if err := ResizeContainerTTY(ctx, nameOrId, &h, &w); err != nil {
+ logrus.Warnf("failed to resize TTY: " + err.Error())
+ }
+ }
+ }
+ }()
+ }
+
+ response, err := conn.DoRequest(stdin, http.MethodPost, "/containers/%s/attach", params, nil, nameOrId)
+ if err != nil {
+ return err
+ }
+ if !(response.IsSuccess() || response.IsInformational()) {
+ return response.Process(nil)
+ }
+
+ // If we are attaching around a start, we need to "signal"
+ // back that we are in fact attached so that started does
+ // not execute before we can attach.
+ if attachReady != nil {
+ attachReady <- true
+ }
+
+ buffer := make([]byte, 1024)
+ if ctnr.Config.Tty {
+ if !isSet.stdout {
+ return fmt.Errorf("container %q requires stdout to be set", ctnr.ID)
+ }
+ // If not multiplex'ed, read from server and write to stdout
+ _, err := io.Copy(stdout, response.Body)
+ if err != nil {
+ return err
+ }
+ } else {
+ for {
+ // Read multiplexed channels and write to appropriate stream
+ fd, l, err := DemuxHeader(response.Body, buffer)
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ return nil
+ }
+ return err
+ }
+ frame, err := DemuxFrame(response.Body, buffer, l)
+ if err != nil {
+ return err
+ }
+
+ switch {
+ case fd == 0 && isSet.stdout:
+ _, err := stdout.Write(frame[0:l])
+ if err != nil {
+ return err
+ }
+ case fd == 1 && isSet.stdout:
+ _, err := stdout.Write(frame[0:l])
+ if err != nil {
+ return err
+ }
+ case fd == 2 && isSet.stderr:
+ _, err := stderr.Write(frame[0:l])
+ if err != nil {
+ return err
+ }
+ case fd == 3:
+ return fmt.Errorf("error from service from stream: %s", frame)
+ default:
+ return fmt.Errorf("unrecognized channel in header: %d, 0-3 supported", fd)
+ }
+ }
+ }
+ return nil
+}
+
+// DemuxHeader reads header for stream from server multiplexed stdin/stdout/stderr/2nd error channel
+func DemuxHeader(r io.Reader, buffer []byte) (fd, sz int, err error) {
+ n, err := io.ReadFull(r, buffer[0:8])
+ if err != nil {
+ return
+ }
+ if n < 8 {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+
+ fd = int(buffer[0])
+ if fd < 0 || fd > 3 {
+ err = errors.Wrapf(ErrLostSync, fmt.Sprintf(`channel "%d" found, 0-3 supported`, fd))
+ return
+ }
+
+ sz = int(binary.BigEndian.Uint32(buffer[4:8]))
+ return
+}
+
+// DemuxFrame reads contents for frame from server multiplexed stdin/stdout/stderr/2nd error channel
+func DemuxFrame(r io.Reader, buffer []byte, length int) (frame []byte, err error) {
+ if len(buffer) < length {
+ buffer = append(buffer, make([]byte, length-len(buffer)+1)...)
+ }
+
+ n, err := io.ReadFull(r, buffer[0:length])
+ if err != nil {
+ return nil, nil
+ }
+ if n < length {
+ err = io.ErrUnexpectedEOF
+ return
+ }
+
+ return buffer[0:length], nil
+}
+
+// ResizeContainerTTY sets container's TTY height and width in characters
+func ResizeContainerTTY(ctx context.Context, nameOrId string, height *int, width *int) error {
+ return resizeTTY(ctx, bindings.JoinURL("containers", nameOrId, "resize"), height, width)
+}
+
+// ResizeExecTTY sets session's TTY height and width in characters
+func ResizeExecTTY(ctx context.Context, nameOrId string, height *int, width *int) error {
+ return resizeTTY(ctx, bindings.JoinURL("exec", nameOrId, "resize"), height, width)
+}
+
+// resizeTTY set size of TTY of container
+func resizeTTY(ctx context.Context, endpoint string, height *int, width *int) error {
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return err
+ }
+
+ params := url.Values{}
+ if height != nil {
+ params.Set("h", strconv.Itoa(*height))
+ }
+ if width != nil {
+ params.Set("w", strconv.Itoa(*width))
+ }
+ rsp, err := conn.DoRequest(nil, http.MethodPost, endpoint, params, nil)
+ if err != nil {
+ return err
+ }
+ return rsp.Process(nil)
+}
+
+type rawFormatter struct {
+ logrus.TextFormatter
+}
+
+func (f *rawFormatter) Format(entry *logrus.Entry) ([]byte, error) {
+ buffer, err := f.TextFormatter.Format(entry)
+ if err != nil {
+ return buffer, err
+ }
+ return append(buffer, '\r'), nil
+}
diff --git a/pkg/bindings/containers/create.go b/pkg/bindings/containers/create.go
index 21355f24b..4603b8653 100644
--- a/pkg/bindings/containers/create.go
+++ b/pkg/bindings/containers/create.go
@@ -22,7 +22,7 @@ func CreateWithSpec(ctx context.Context, s *specgen.SpecGenerator) (entities.Con
return ccr, err
}
stringReader := strings.NewReader(specgenString)
- response, err := conn.DoRequest(stringReader, http.MethodPost, "/containers/create", nil)
+ response, err := conn.DoRequest(stringReader, http.MethodPost, "/containers/create", nil, nil)
if err != nil {
return ccr, err
}
diff --git a/pkg/bindings/containers/diff.go b/pkg/bindings/containers/diff.go
index 82070ca9a..06a828c30 100644
--- a/pkg/bindings/containers/diff.go
+++ b/pkg/bindings/containers/diff.go
@@ -15,7 +15,7 @@ func Diff(ctx context.Context, nameOrId string) ([]archive.Change, error) {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/changes", nil, nameOrId)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/changes", nil, nil, nameOrId)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/containers/exec.go b/pkg/bindings/containers/exec.go
index 48f9ed697..2aeeae1f8 100644
--- a/pkg/bindings/containers/exec.go
+++ b/pkg/bindings/containers/exec.go
@@ -34,7 +34,7 @@ func ExecCreate(ctx context.Context, nameOrID string, config *handlers.ExecCreat
}
jsonReader := strings.NewReader(string(requestJSON))
- resp, err := conn.DoRequest(jsonReader, http.MethodPost, "/containers/%s/exec", nil, nameOrID)
+ resp, err := conn.DoRequest(jsonReader, http.MethodPost, "/containers/%s/exec", nil, nil, nameOrID)
if err != nil {
return "", err
}
@@ -57,7 +57,7 @@ func ExecInspect(ctx context.Context, sessionID string) (*define.InspectExecSess
logrus.Debugf("Inspecting session ID %q", sessionID)
- resp, err := conn.DoRequest(nil, http.MethodGet, "/exec/%s/json", nil, sessionID)
+ resp, err := conn.DoRequest(nil, http.MethodGet, "/exec/%s/json", nil, nil, sessionID)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/containers/healthcheck.go b/pkg/bindings/containers/healthcheck.go
index 2b783ac73..b726acf49 100644
--- a/pkg/bindings/containers/healthcheck.go
+++ b/pkg/bindings/containers/healthcheck.go
@@ -18,7 +18,7 @@ func RunHealthCheck(ctx context.Context, nameOrID string) (*define.HealthCheckRe
var (
status define.HealthCheckResults
)
- response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/healthcheck", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/healthcheck", nil, nil, nameOrID)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/containers/logs.go b/pkg/bindings/containers/logs.go
index b7ecb3c7e..bec4ebb3c 100644
--- a/pkg/bindings/containers/logs.go
+++ b/pkg/bindings/containers/logs.go
@@ -1,8 +1,9 @@
package containers
import (
+ "bytes"
"context"
- "encoding/binary"
+ "fmt"
"io"
"net/http"
"net/url"
@@ -45,72 +46,37 @@ func Logs(ctx context.Context, nameOrID string, opts LogOptions, stdoutChan, std
if opts.Stdout == nil && opts.Stderr == nil {
params.Set("stdout", strconv.FormatBool(true))
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/logs", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/logs", params, nil, nameOrID)
if err != nil {
return err
}
- // read 8 bytes
- // first byte determines stderr=2|stdout=1
- // bytes 4-7 len(msg) in uint32
+ buffer := make([]byte, 1024)
for {
- stream, msgSize, err := readHeader(response.Body)
+ fd, l, err := DemuxHeader(response.Body, buffer)
if err != nil {
- // In case the server side closes up shop because !follow
- if err == io.EOF {
- break
+ if errors.Is(err, io.EOF) {
+ return nil
}
- return errors.Wrap(err, "unable to read log header")
+ return err
}
- msg, err := readMsg(response.Body, msgSize)
+ frame, err := DemuxFrame(response.Body, buffer, l)
if err != nil {
- return errors.Wrap(err, "unable to read log message")
+ return err
}
- if stream == 1 {
- stdoutChan <- msg
- } else {
- stderrChan <- msg
- }
- }
- return nil
-}
+ frame = bytes.Replace(frame[0:l], []byte{13}, []byte{10}, -1)
-func readMsg(r io.Reader, msgSize int) (string, error) {
- var msg []byte
- size := msgSize
- for {
- b := make([]byte, size)
- _, err := r.Read(b)
- if err != nil {
- return "", err
- }
- msg = append(msg, b...)
- if len(msg) == msgSize {
- break
- }
- size = msgSize - len(msg)
- }
- return string(msg), nil
-}
-
-func readHeader(r io.Reader) (byte, int, error) {
- var (
- header []byte
- size = 8
- )
- for {
- b := make([]byte, size)
- _, err := r.Read(b)
- if err != nil {
- return 0, 0, err
- }
- header = append(header, b...)
- if len(header) == 8 {
- break
+ switch fd {
+ case 0:
+ stdoutChan <- string(frame)
+ case 1:
+ stdoutChan <- string(frame)
+ case 2:
+ stderrChan <- string(frame)
+ case 3:
+ return errors.New("error from service in stream: " + string(frame))
+ default:
+ return fmt.Errorf("unrecognized input header: %d", fd)
}
- size = 8 - len(header)
}
- stream := header[0]
- msgSize := int(binary.BigEndian.Uint32(header[4:]) - 8)
- return stream, msgSize, nil
}
diff --git a/pkg/bindings/containers/mount.go b/pkg/bindings/containers/mount.go
index e0627d9a3..2d553142f 100644
--- a/pkg/bindings/containers/mount.go
+++ b/pkg/bindings/containers/mount.go
@@ -17,7 +17,7 @@ func Mount(ctx context.Context, nameOrID string) (string, error) {
var (
path string
)
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/mount", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/mount", nil, nil, nameOrID)
if err != nil {
return path, err
}
@@ -31,7 +31,7 @@ func Unmount(ctx context.Context, nameOrID string) error {
if err != nil {
return err
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/unmount", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/unmount", nil, nil, nameOrID)
if err != nil {
return err
}
@@ -45,7 +45,7 @@ func GetMountedContainerPaths(ctx context.Context) (map[string]string, error) {
return nil, err
}
mounts := make(map[string]string)
- response, err := conn.DoRequest(nil, http.MethodGet, "/containers/showmounted", nil)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/containers/showmounted", nil, nil)
if err != nil {
return mounts, err
}
diff --git a/pkg/bindings/generate/generate.go b/pkg/bindings/generate/generate.go
index 2916754b8..161b722f3 100644
--- a/pkg/bindings/generate/generate.go
+++ b/pkg/bindings/generate/generate.go
@@ -1,4 +1,32 @@
package generate
-func GenerateKube() {}
-func GenerateSystemd() {}
+import (
+ "context"
+ "net/http"
+ "net/url"
+ "strconv"
+
+ "github.com/containers/libpod/pkg/bindings"
+ "github.com/containers/libpod/pkg/domain/entities"
+)
+
+func GenerateKube(ctx context.Context, nameOrID string, options entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) {
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+ params := url.Values{}
+ params.Set("service", strconv.FormatBool(options.Service))
+
+ response, err := conn.DoRequest(nil, http.MethodGet, "/generate/%s/kube", params, nil, nameOrID)
+ if err != nil {
+ return nil, err
+ }
+
+ if response.StatusCode == http.StatusOK {
+ return &entities.GenerateKubeReport{Reader: response.Body}, nil
+ }
+
+ // Unpack the error.
+ return nil, response.Process(nil)
+}
diff --git a/pkg/bindings/images/diff.go b/pkg/bindings/images/diff.go
index cfdd06a97..e2d344ea0 100644
--- a/pkg/bindings/images/diff.go
+++ b/pkg/bindings/images/diff.go
@@ -15,7 +15,7 @@ func Diff(ctx context.Context, nameOrId string) ([]archive.Change, error) {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/changes", nil, nameOrId)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/changes", nil, nil, nameOrId)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go
index 2305e0101..e0802a6e1 100644
--- a/pkg/bindings/images/images.go
+++ b/pkg/bindings/images/images.go
@@ -1,6 +1,7 @@
package images
import (
+ "bytes"
"context"
"fmt"
"io"
@@ -8,10 +9,14 @@ import (
"net/url"
"strconv"
+ "github.com/containers/buildah"
"github.com/containers/image/v5/types"
"github.com/containers/libpod/pkg/api/handlers"
+ "github.com/containers/libpod/pkg/auth"
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/domain/entities"
+ "github.com/docker/go-units"
+ jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
)
@@ -22,7 +27,7 @@ func Exists(ctx context.Context, nameOrID string) (bool, error) {
if err != nil {
return false, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/exists", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/exists", nil, nil, nameOrID)
if err != nil {
return false, err
}
@@ -48,7 +53,7 @@ func List(ctx context.Context, all *bool, filters map[string][]string) ([]*entit
}
params.Set("filters", strFilters)
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/images/json", params)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/images/json", params, nil)
if err != nil {
return imageSummary, err
}
@@ -67,15 +72,29 @@ func GetImage(ctx context.Context, nameOrID string, size *bool) (*entities.Image
params.Set("size", strconv.FormatBool(*size))
}
inspectedData := entities.ImageInspectReport{}
- response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/json", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/json", params, nil, nameOrID)
if err != nil {
return &inspectedData, err
}
return &inspectedData, response.Process(&inspectedData)
}
-func Tree(ctx context.Context, nameOrId string) error {
- return bindings.ErrNotImplemented
+// Tree retrieves a "tree" based representation of the given image
+func Tree(ctx context.Context, nameOrId string, whatRequires *bool) (*entities.ImageTreeReport, error) {
+ var report entities.ImageTreeReport
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+ params := url.Values{}
+ if whatRequires != nil {
+ params.Set("size", strconv.FormatBool(*whatRequires))
+ }
+ response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/tree", params, nil, nameOrId)
+ if err != nil {
+ return nil, err
+ }
+ return &report, response.Process(&report)
}
// History returns the parent layers of an image.
@@ -85,7 +104,7 @@ func History(ctx context.Context, nameOrID string) ([]*handlers.HistoryResponse,
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/history", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/history", nil, nil, nameOrID)
if err != nil {
return history, err
}
@@ -102,43 +121,13 @@ func Load(ctx context.Context, r io.Reader, name *string) (*entities.ImageLoadRe
if name != nil {
params.Set("reference", *name)
}
- response, err := conn.DoRequest(r, http.MethodPost, "/images/load", params)
+ response, err := conn.DoRequest(r, http.MethodPost, "/images/load", params, nil)
if err != nil {
return nil, err
}
return &report, response.Process(&report)
}
-// Remove deletes an image from local storage. The optional force parameter
-// will forcibly remove the image by removing all all containers, including
-// those that are Running, first.
-func Remove(ctx context.Context, images []string, opts entities.ImageRemoveOptions) (*entities.ImageRemoveReport, error) {
- var report handlers.LibpodImagesRemoveReport
- conn, err := bindings.GetClient(ctx)
- if err != nil {
- return nil, err
- }
- params := url.Values{}
- params.Set("all", strconv.FormatBool(opts.All))
- params.Set("force", strconv.FormatBool(opts.Force))
- for _, i := range images {
- params.Add("images", i)
- }
-
- response, err := conn.DoRequest(nil, http.MethodGet, "/images/remove", params)
- if err != nil {
- return nil, err
- }
- if err := response.Process(&report); err != nil {
- return nil, err
- }
- var rmError error
- if report.Error != "" {
- rmError = errors.New(report.Error)
- }
- return &report.ImageRemoveReport, rmError
-}
-
// Export saves an image from local storage as a tarball or image archive. The optional format
// parameter is used to change the format of the output.
func Export(ctx context.Context, nameOrID string, w io.Writer, format *string, compress *bool) error {
@@ -153,7 +142,7 @@ func Export(ctx context.Context, nameOrID string, w io.Writer, format *string, c
if compress != nil {
params.Set("compress", strconv.FormatBool(*compress))
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/get", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/get", params, nil, nameOrID)
if err != nil {
return err
}
@@ -162,7 +151,7 @@ func Export(ctx context.Context, nameOrID string, w io.Writer, format *string, c
_, err = io.Copy(w, response.Body)
return err
}
- return nil
+ return response.Process(nil)
}
// Prune removes unused images from local storage. The optional filters can be used to further
@@ -186,7 +175,7 @@ func Prune(ctx context.Context, all *bool, filters map[string][]string) ([]strin
}
params.Set("filters", stringFilter)
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/images/prune", params)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/images/prune", params, nil)
if err != nil {
return deleted, err
}
@@ -202,7 +191,7 @@ func Tag(ctx context.Context, nameOrID, tag, repo string) error {
params := url.Values{}
params.Set("tag", tag)
params.Set("repo", repo)
- response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/tag", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/tag", params, nil, nameOrID)
if err != nil {
return err
}
@@ -218,14 +207,115 @@ func Untag(ctx context.Context, nameOrID, tag, repo string) error {
params := url.Values{}
params.Set("tag", tag)
params.Set("repo", repo)
- response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/untag", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/untag", params, nil, nameOrID)
if err != nil {
return err
}
return response.Process(nil)
}
-func Build(nameOrId string) {}
+// Build creates an image using a containerfile reference
+func Build(ctx context.Context, containerFiles []string, options entities.BuildOptions, tarfile io.Reader) (*entities.BuildReport, error) {
+ var (
+ platform string
+ report entities.BuildReport
+ )
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+ params := url.Values{}
+ params.Set("dockerfile", containerFiles[0])
+ if t := options.Output; len(t) > 0 {
+ params.Set("t", t)
+ }
+ // TODO Remote, Quiet
+ if options.NoCache {
+ params.Set("nocache", "1")
+ }
+ // TODO cachefrom
+ if options.PullPolicy == buildah.PullAlways {
+ params.Set("pull", "1")
+ }
+ if options.RemoveIntermediateCtrs {
+ params.Set("rm", "1")
+ }
+ if options.ForceRmIntermediateCtrs {
+ params.Set("forcerm", "1")
+ }
+ if mem := options.CommonBuildOpts.Memory; mem > 0 {
+ params.Set("memory", strconv.Itoa(int(mem)))
+ }
+ if memSwap := options.CommonBuildOpts.MemorySwap; memSwap > 0 {
+ params.Set("memswap", strconv.Itoa(int(memSwap)))
+ }
+ if cpuShares := options.CommonBuildOpts.CPUShares; cpuShares > 0 {
+ params.Set("cpushares", strconv.Itoa(int(cpuShares)))
+ }
+ if cpuSetCpus := options.CommonBuildOpts.CPUSetCPUs; len(cpuSetCpus) > 0 {
+ params.Set("cpusetcpues", cpuSetCpus)
+ }
+ if cpuPeriod := options.CommonBuildOpts.CPUPeriod; cpuPeriod > 0 {
+ params.Set("cpuperiod", strconv.Itoa(int(cpuPeriod)))
+ }
+ if cpuQuota := options.CommonBuildOpts.CPUQuota; cpuQuota > 0 {
+ params.Set("cpuquota", strconv.Itoa(int(cpuQuota)))
+ }
+ if buildArgs := options.Args; len(buildArgs) > 0 {
+ bArgs, err := jsoniter.MarshalToString(buildArgs)
+ if err != nil {
+ return nil, err
+ }
+ params.Set("buildargs", bArgs)
+ }
+ if shmSize := options.CommonBuildOpts.ShmSize; len(shmSize) > 0 {
+ shmBytes, err := units.RAMInBytes(shmSize)
+ if err != nil {
+ return nil, err
+ }
+ params.Set("shmsize", strconv.Itoa(int(shmBytes)))
+ }
+ if options.Squash {
+ params.Set("squash", "1")
+ }
+ if labels := options.Labels; len(labels) > 0 {
+ l, err := jsoniter.MarshalToString(labels)
+ if err != nil {
+ return nil, err
+ }
+ params.Set("labels", l)
+ }
+
+ // TODO network?
+ if OS := options.OS; len(OS) > 0 {
+ platform += OS
+ }
+ if arch := options.Architecture; len(arch) > 0 {
+ platform += "/" + arch
+ }
+ if len(platform) > 0 {
+ params.Set("platform", platform)
+ }
+ // TODO outputs?
+
+ response, err := conn.DoRequest(tarfile, http.MethodPost, "/build", params, nil)
+ if err != nil {
+ return nil, err
+ }
+ var streamReponse []byte
+ bb := bytes.NewBuffer(streamReponse)
+ if _, err = io.Copy(bb, response.Body); err != nil {
+ return nil, err
+ }
+ var s struct {
+ Stream string `json:"stream"`
+ }
+ if err := jsoniter.UnmarshalFromString(bb.String(), &s); err != nil {
+ return nil, err
+ }
+ fmt.Print(s.Stream)
+ return &report, nil
+}
// Imports adds the given image to the local image store. This can be done by file and the given reader
// or via the url parameter. Additional metadata can be associated with the image by using the changes and
@@ -252,7 +342,7 @@ func Import(ctx context.Context, changes []string, message, reference, u *string
if u != nil {
params.Set("url", *u)
}
- response, err := conn.DoRequest(r, http.MethodPost, "/images/import", params)
+ response, err := conn.DoRequest(r, http.MethodPost, "/images/import", params, nil)
if err != nil {
return nil, err
}
@@ -270,16 +360,22 @@ func Pull(ctx context.Context, rawImage string, options entities.ImagePullOption
}
params := url.Values{}
params.Set("reference", rawImage)
- params.Set("credentials", options.Credentials)
params.Set("overrideArch", options.OverrideArch)
params.Set("overrideOS", options.OverrideOS)
- if options.TLSVerify != types.OptionalBoolUndefined {
- val := bool(options.TLSVerify == types.OptionalBoolTrue)
- params.Set("tlsVerify", strconv.FormatBool(val))
+ if options.SkipTLSVerify != types.OptionalBoolUndefined {
+ // Note: we have to verify if skipped is false.
+ verifyTLS := bool(options.SkipTLSVerify == types.OptionalBoolFalse)
+ params.Set("tlsVerify", strconv.FormatBool(verifyTLS))
}
params.Set("allTags", strconv.FormatBool(options.AllTags))
- response, err := conn.DoRequest(nil, http.MethodPost, "/images/pull", params)
+ // TODO: have a global system context we can pass around (1st argument)
+ header, err := auth.Header(nil, options.Authfile, options.Username, options.Password)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := conn.DoRequest(nil, http.MethodPost, "/images/pull", params, header)
if err != nil {
return nil, err
}
@@ -307,17 +403,28 @@ func Push(ctx context.Context, source string, destination string, options entiti
if err != nil {
return err
}
+
+ // TODO: have a global system context we can pass around (1st argument)
+ header, err := auth.Header(nil, options.Authfile, options.Username, options.Password)
+ if err != nil {
+ return err
+ }
+
params := url.Values{}
- params.Set("credentials", options.Credentials)
params.Set("destination", destination)
- if options.TLSVerify != types.OptionalBoolUndefined {
- val := bool(options.TLSVerify == types.OptionalBoolTrue)
- params.Set("tlsVerify", strconv.FormatBool(val))
+ if options.SkipTLSVerify != types.OptionalBoolUndefined {
+ // Note: we have to verify if skipped is false.
+ verifyTLS := bool(options.SkipTLSVerify == types.OptionalBoolFalse)
+ params.Set("tlsVerify", strconv.FormatBool(verifyTLS))
}
path := fmt.Sprintf("/images/%s/push", source)
- _, err = conn.DoRequest(nil, http.MethodPost, path, params)
- return err
+ response, err := conn.DoRequest(nil, http.MethodPost, path, params, header)
+ if err != nil {
+ return err
+ }
+
+ return response.Process(err)
}
// Search is the binding for libpod's v2 endpoints for Search images.
@@ -333,12 +440,19 @@ func Search(ctx context.Context, term string, opts entities.ImageSearchOptions)
params.Set("filters", f)
}
- if opts.TLSVerify != types.OptionalBoolUndefined {
- val := bool(opts.TLSVerify == types.OptionalBoolTrue)
- params.Set("tlsVerify", strconv.FormatBool(val))
+ if opts.SkipTLSVerify != types.OptionalBoolUndefined {
+ // Note: we have to verify if skipped is false.
+ verifyTLS := bool(opts.SkipTLSVerify == types.OptionalBoolFalse)
+ params.Set("tlsVerify", strconv.FormatBool(verifyTLS))
+ }
+
+ // TODO: have a global system context we can pass around (1st argument)
+ header, err := auth.Header(nil, opts.Authfile, "", "")
+ if err != nil {
+ return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/images/search", params)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/images/search", params, header)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/images/rm.go b/pkg/bindings/images/rm.go
new file mode 100644
index 000000000..c315bfce7
--- /dev/null
+++ b/pkg/bindings/images/rm.go
@@ -0,0 +1,65 @@
+package images
+
+import (
+ "context"
+ "net/http"
+ "net/url"
+ "strconv"
+
+ "github.com/containers/libpod/pkg/api/handlers"
+ "github.com/containers/libpod/pkg/bindings"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/errorhandling"
+)
+
+// BachtRemove removes a batch of images from the local storage.
+func BatchRemove(ctx context.Context, images []string, opts entities.ImageRemoveOptions) (*entities.ImageRemoveReport, []error) {
+ // 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 handlers.LibpodImagesRemoveReport
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, []error{err}
+ }
+
+ params := url.Values{}
+ params.Set("all", strconv.FormatBool(opts.All))
+ params.Set("force", strconv.FormatBool(opts.Force))
+ for _, i := range images {
+ params.Add("images", i)
+ }
+
+ response, err := conn.DoRequest(nil, http.MethodDelete, "/images/remove", params, nil)
+ if err != nil {
+ return nil, []error{err}
+ }
+ if err := response.Process(&report); err != nil {
+ return nil, []error{err}
+ }
+
+ return &report.ImageRemoveReport, errorhandling.StringsToErrors(report.Errors)
+}
+
+// Remove removes an image from the local storage. Use force to remove an
+// image, even if it's used by containers.
+func Remove(ctx context.Context, nameOrID string, force bool) (*entities.ImageRemoveReport, error) {
+ var report handlers.LibpodImagesRemoveReport
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ params := url.Values{}
+ params.Set("force", strconv.FormatBool(force))
+ response, err := conn.DoRequest(nil, http.MethodDelete, "/images/%s", params, nil, nameOrID)
+ if err != nil {
+ return nil, err
+ }
+ if err := response.Process(&report); err != nil {
+ return nil, err
+ }
+
+ errs := errorhandling.StringsToErrors(report.Errors)
+ return &report.ImageRemoveReport, errorhandling.JoinErrors(errs)
+}
diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go
index a8d1e6ca3..e89624667 100644
--- a/pkg/bindings/manifests/manifests.go
+++ b/pkg/bindings/manifests/manifests.go
@@ -39,7 +39,7 @@ func Create(ctx context.Context, names, images []string, all *bool) (string, err
params.Add("image", i)
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/manifests/create", params)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/manifests/create", params, nil)
if err != nil {
return "", err
}
@@ -53,7 +53,7 @@ func Inspect(ctx context.Context, name string) (*manifest.Schema2List, error) {
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/manifests/%s/json", nil, name)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/manifests/%s/json", nil, nil, name)
if err != nil {
return nil, err
}
@@ -73,7 +73,7 @@ func Add(ctx context.Context, name string, options image.ManifestAddOpts) (strin
return "", err
}
stringReader := strings.NewReader(optionsString)
- response, err := conn.DoRequest(stringReader, http.MethodPost, "/manifests/%s/add", nil, name)
+ response, err := conn.DoRequest(stringReader, http.MethodPost, "/manifests/%s/add", nil, nil, name)
if err != nil {
return "", err
}
@@ -90,7 +90,7 @@ func Remove(ctx context.Context, name, digest string) (string, error) {
}
params := url.Values{}
params.Set("digest", digest)
- response, err := conn.DoRequest(nil, http.MethodDelete, "/manifests/%s", params, name)
+ response, err := conn.DoRequest(nil, http.MethodDelete, "/manifests/%s", params, nil, name)
if err != nil {
return "", err
}
@@ -112,15 +112,37 @@ func Push(ctx context.Context, name string, destination *string, all *bool) (str
params := url.Values{}
params.Set("image", name)
if destination != nil {
- dest = name
+ dest = *destination
}
params.Set("destination", dest)
if all != nil {
params.Set("all", strconv.FormatBool(*all))
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/manifests/%s/push", params, name)
+ _, err = conn.DoRequest(nil, http.MethodPost, "/manifests/%s/push", params, nil, name)
if err != nil {
return "", err
}
- return idr.ID, response.Process(&idr)
+ return idr.ID, err
}
+
+// There is NO annotate endpoint. this binding could never work
+// Annotate updates the image configuration of a given manifest list
+//func Annotate(ctx context.Context, name, digest string, options image.ManifestAnnotateOpts) (string, error) {
+// var idr handlers.IDResponse
+// conn, err := bindings.GetClient(ctx)
+// if err != nil {
+// return "", err
+// }
+// params := url.Values{}
+// params.Set("digest", digest)
+// optionsString, err := jsoniter.MarshalToString(options)
+// if err != nil {
+// return "", err
+// }
+// stringReader := strings.NewReader(optionsString)
+// response, err := conn.DoRequest(stringReader, http.MethodPost, "/manifests/%s/annotate", params, name)
+// if err != nil {
+// return "", err
+// }
+// return idr.ID, response.Process(&idr)
+//}
diff --git a/pkg/bindings/network/network.go b/pkg/bindings/network/network.go
index c95b22953..34881b524 100644
--- a/pkg/bindings/network/network.go
+++ b/pkg/bindings/network/network.go
@@ -3,46 +3,82 @@ package network
import (
"context"
"net/http"
+ "net/url"
+ "strconv"
+ "strings"
- "github.com/containernetworking/cni/libcni"
"github.com/containers/libpod/pkg/bindings"
+ "github.com/containers/libpod/pkg/domain/entities"
+ jsoniter "github.com/json-iterator/go"
)
-func Create() {}
-func Inspect(ctx context.Context, nameOrID string) (map[string]interface{}, error) {
+// Create makes a new CNI network configuration
+func Create(ctx context.Context, options entities.NetworkCreateOptions, name *string) (*entities.NetworkCreateReport, error) {
+ var report entities.NetworkCreateReport
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- n := make(map[string]interface{})
- response, err := conn.DoRequest(nil, http.MethodGet, "/networks/%s/json", nil, nameOrID)
+ params := url.Values{}
+ if name != nil {
+ params.Set("name", *name)
+ }
+ networkConfig, err := jsoniter.MarshalToString(options)
if err != nil {
- return n, err
+ return nil, err
+ }
+ stringReader := strings.NewReader(networkConfig)
+ response, err := conn.DoRequest(stringReader, http.MethodPost, "/networks/create", params, nil)
+ if err != nil {
+ return nil, err
}
- return n, response.Process(&n)
+ return &report, response.Process(&report)
}
-func Remove(ctx context.Context, nameOrID string) error {
+// Inspect returns low level information about a CNI network configuration
+func Inspect(ctx context.Context, nameOrID string) ([]entities.NetworkInspectReport, error) {
+ var reports []entities.NetworkInspectReport
conn, err := bindings.GetClient(ctx)
if err != nil {
- return err
+ return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodDelete, "/networks/%s", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/networks/%s/json", nil, nil, nameOrID)
if err != nil {
- return err
+ return nil, err
+ }
+ return reports, response.Process(&reports)
+}
+
+// Remove deletes a defined CNI network configuration by name. The optional force boolean
+// will remove all containers associated with the network when set to true. A slice
+// of NetworkRemoveReports are returned.
+func Remove(ctx context.Context, nameOrID string, force *bool) ([]*entities.NetworkRmReport, error) {
+ var reports []*entities.NetworkRmReport
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+ params := url.Values{}
+ if force != nil {
+ params.Set("size", strconv.FormatBool(*force))
+ }
+ response, err := conn.DoRequest(nil, http.MethodDelete, "/networks/%s", params, nil, nameOrID)
+ if err != nil {
+ return nil, err
}
- return response.Process(nil)
+ return reports, response.Process(&reports)
}
-func List(ctx context.Context) ([]*libcni.NetworkConfigList, error) {
+// List returns a summary of all CNI network configurations
+func List(ctx context.Context) ([]*entities.NetworkListReport, error) {
var (
- netList []*libcni.NetworkConfigList
+ netList []*entities.NetworkListReport
)
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/networks/json", nil)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/networks/json", nil, nil)
if err != nil {
return netList, err
}
diff --git a/pkg/bindings/play/play.go b/pkg/bindings/play/play.go
index a6f03cad2..288cca454 100644
--- a/pkg/bindings/play/play.go
+++ b/pkg/bindings/play/play.go
@@ -1,7 +1,50 @@
package play
-import "github.com/containers/libpod/pkg/bindings"
+import (
+ "context"
+ "net/http"
+ "net/url"
+ "os"
+ "strconv"
-func PlayKube() error {
- return bindings.ErrNotImplemented
+ "github.com/containers/image/v5/types"
+ "github.com/containers/libpod/pkg/auth"
+ "github.com/containers/libpod/pkg/bindings"
+ "github.com/containers/libpod/pkg/domain/entities"
+)
+
+func PlayKube(ctx context.Context, path string, options entities.PlayKubeOptions) (*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
+ }
+ defer f.Close()
+
+ params := url.Values{}
+ params.Set("network", options.Network)
+ if options.SkipTLSVerify != types.OptionalBoolUndefined {
+ params.Set("tlsVerify", strconv.FormatBool(options.SkipTLSVerify == types.OptionalBoolTrue))
+ }
+
+ // TODO: have a global system context we can pass around (1st argument)
+ header, err := auth.Header(nil, options.Authfile, options.Username, options.Password)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := conn.DoRequest(f, http.MethodPost, "/play/kube", params, header)
+ if err != nil {
+ return nil, err
+ }
+ if err := response.Process(&report); err != nil {
+ return nil, err
+ }
+
+ return &report, nil
}
diff --git a/pkg/bindings/pods/pods.go b/pkg/bindings/pods/pods.go
index b213c8c73..fb273fdf3 100644
--- a/pkg/bindings/pods/pods.go
+++ b/pkg/bindings/pods/pods.go
@@ -28,7 +28,7 @@ func CreatePodFromSpec(ctx context.Context, s *specgen.PodSpecGenerator) (*entit
return nil, err
}
stringReader := strings.NewReader(specgenString)
- response, err := conn.DoRequest(stringReader, http.MethodPost, "/pods/create", nil)
+ response, err := conn.DoRequest(stringReader, http.MethodPost, "/pods/create", nil, nil)
if err != nil {
return nil, err
}
@@ -41,7 +41,7 @@ func Exists(ctx context.Context, nameOrID string) (bool, error) {
if err != nil {
return false, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/pods/%s/exists", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/pods/%s/exists", nil, nil, nameOrID)
if err != nil {
return false, err
}
@@ -57,7 +57,7 @@ func Inspect(ctx context.Context, nameOrID string) (*entities.PodInspectReport,
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/pods/%s/json", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/pods/%s/json", nil, nil, nameOrID)
if err != nil {
return nil, err
}
@@ -78,7 +78,7 @@ func Kill(ctx context.Context, nameOrID string, signal *string) (*entities.PodKi
if signal != nil {
params.Set("signal", *signal)
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/kill", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/kill", params, nil, nameOrID)
if err != nil {
return nil, err
}
@@ -92,7 +92,7 @@ func Pause(ctx context.Context, nameOrID string) (*entities.PodPauseReport, erro
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/pause", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/pause", nil, nil, nameOrID)
if err != nil {
return nil, err
}
@@ -107,7 +107,7 @@ func Prune(ctx context.Context) ([]*entities.PodPruneReport, error) {
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/pods/prune", nil)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/pods/prune", nil, nil)
if err != nil {
return nil, err
}
@@ -132,7 +132,7 @@ func List(ctx context.Context, filters map[string][]string) ([]*entities.ListPod
}
params.Set("filters", stringFilter)
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/pods/json", params)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/pods/json", params, nil)
if err != nil {
return podsReports, err
}
@@ -146,7 +146,7 @@ func Restart(ctx context.Context, nameOrID string) (*entities.PodRestartReport,
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/restart", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/restart", nil, nil, nameOrID)
if err != nil {
return nil, err
}
@@ -165,7 +165,7 @@ func Remove(ctx context.Context, nameOrID string, force *bool) (*entities.PodRmR
if force != nil {
params.Set("force", strconv.FormatBool(*force))
}
- response, err := conn.DoRequest(nil, http.MethodDelete, "/pods/%s", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodDelete, "/pods/%s", params, nil, nameOrID)
if err != nil {
return nil, err
}
@@ -179,7 +179,7 @@ func Start(ctx context.Context, nameOrID string) (*entities.PodStartReport, erro
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/start", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/start", nil, nil, nameOrID)
if err != nil {
return nil, err
}
@@ -202,7 +202,7 @@ func Stop(ctx context.Context, nameOrID string, timeout *int) (*entities.PodStop
if timeout != nil {
params.Set("t", strconv.Itoa(*timeout))
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/stop", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/stop", params, nil, nameOrID)
if err != nil {
return nil, err
}
@@ -226,7 +226,7 @@ func Top(ctx context.Context, nameOrID string, descriptors []string) ([]string,
// flatten the slice into one string
params.Set("ps_args", strings.Join(descriptors, ","))
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/pods/%s/top", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/pods/%s/top", params, nil, nameOrID)
if err != nil {
return nil, err
}
@@ -254,7 +254,7 @@ func Unpause(ctx context.Context, nameOrID string) (*entities.PodUnpauseReport,
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/unpause", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/unpause", nil, nil, nameOrID)
if err != nil {
return nil, err
}
@@ -277,7 +277,7 @@ func Stats(ctx context.Context, namesOrIDs []string, options entities.PodStatsOp
params.Set("all", strconv.FormatBool(options.All))
var reports []*entities.PodStatsReport
- response, err := conn.DoRequest(nil, http.MethodGet, "/pods/stats", params)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/pods/stats", params, nil)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/system/info.go b/pkg/bindings/system/info.go
index 13e12645d..8ad704f84 100644
--- a/pkg/bindings/system/info.go
+++ b/pkg/bindings/system/info.go
@@ -15,7 +15,7 @@ func Info(ctx context.Context) (*define.Info, error) {
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/info", nil)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/info", nil, nil)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/system/system.go b/pkg/bindings/system/system.go
index df6b529de..010762bef 100644
--- a/pkg/bindings/system/system.go
+++ b/pkg/bindings/system/system.go
@@ -3,11 +3,14 @@ package system
import (
"context"
"encoding/json"
+ "fmt"
"io"
"net/http"
"net/url"
"strconv"
+ "time"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/pkg/errors"
@@ -17,7 +20,7 @@ import (
// Events allows you to monitor libdpod related events like container creation and
// removal. The events are then passed to the eventChan provided. The optional cancelChan
// can be used to cancel the read of events and close down the HTTP connection.
-func Events(ctx context.Context, eventChan chan (entities.Event), cancelChan chan bool, since, until *string, filters map[string][]string) error {
+func Events(ctx context.Context, eventChan chan entities.Event, cancelChan chan bool, since, until *string, filters map[string][]string, stream *bool) error {
conn, err := bindings.GetClient(ctx)
if err != nil {
return err
@@ -29,6 +32,9 @@ func Events(ctx context.Context, eventChan chan (entities.Event), cancelChan cha
if until != nil {
params.Set("until", *until)
}
+ if stream != nil {
+ params.Set("stream", strconv.FormatBool(*stream))
+ }
if filters != nil {
filterString, err := bindings.FiltersToString(filters)
if err != nil {
@@ -36,7 +42,7 @@ func Events(ctx context.Context, eventChan chan (entities.Event), cancelChan cha
}
params.Set("filters", filterString)
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/events", params)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/events", params, nil)
if err != nil {
return err
}
@@ -47,18 +53,24 @@ func Events(ctx context.Context, eventChan chan (entities.Event), cancelChan cha
logrus.Error(errors.Wrap(err, "unable to close event response body"))
}()
}
+
dec := json.NewDecoder(response.Body)
- for {
- e := entities.Event{}
- if err := dec.Decode(&e); err != nil {
- if err == io.EOF {
- break
- }
- return errors.Wrap(err, "unable to decode event response")
+ for err = (error)(nil); err == nil; {
+ var e = entities.Event{}
+ err = dec.Decode(&e)
+ if err == nil {
+ eventChan <- e
}
- eventChan <- e
}
- return nil
+ close(eventChan)
+ switch {
+ case err == nil:
+ return nil
+ case errors.Is(err, io.EOF):
+ return nil
+ default:
+ return errors.Wrap(err, "unable to decode event response")
+ }
}
// Prune removes all unused system data.
@@ -77,7 +89,57 @@ func Prune(ctx context.Context, all, volumes *bool) (*entities.SystemPruneReport
if volumes != nil {
params.Set("Volumes", strconv.FormatBool(*volumes))
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/system/prune", params)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/system/prune", params, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &report, response.Process(&report)
+}
+
+func Version(ctx context.Context) (*entities.SystemVersionReport, error) {
+ var report entities.SystemVersionReport
+ var component entities.ComponentVersion
+
+ version, err := define.GetVersion()
+ if err != nil {
+ return nil, err
+ }
+ report.Client = &version
+
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+ response, err := conn.DoRequest(nil, http.MethodGet, "/version", nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ if err = response.Process(&component); err != nil {
+ return nil, err
+ }
+ f, _ := strconv.ParseFloat(component.APIVersion, 64)
+ b, _ := time.Parse(time.RFC3339, component.BuildTime)
+ report.Server = &define.Version{
+ APIVersion: int64(f),
+ Version: component.Version.Version,
+ GoVersion: component.GoVersion,
+ GitCommit: component.GitCommit,
+ Built: b.Unix(),
+ OsArch: fmt.Sprintf("%s/%s", component.Os, component.Arch),
+ }
+ return &report, err
+}
+
+// DiskUsage returns information about image, container, and volume disk
+// consumption
+func DiskUsage(ctx context.Context) (*entities.SystemDfReport, error) {
+ var report entities.SystemDfReport
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+ response, err := conn.DoRequest(nil, http.MethodGet, "/system/df", nil, nil)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/test/attach_test.go b/pkg/bindings/test/attach_test.go
new file mode 100644
index 000000000..6fb166828
--- /dev/null
+++ b/pkg/bindings/test/attach_test.go
@@ -0,0 +1,110 @@
+package test_bindings
+
+import (
+ "bytes"
+ "fmt"
+ "time"
+
+ "github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/bindings"
+ "github.com/containers/libpod/pkg/bindings/containers"
+ "github.com/containers/libpod/pkg/specgen"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("Podman containers attach", func() {
+ var (
+ bt *bindingTest
+ s *gexec.Session
+ )
+
+ BeforeEach(func() {
+ bt = newBindingTest()
+ bt.RestoreImagesFromCache()
+ s = bt.startAPIService()
+ time.Sleep(1 * time.Second)
+ err := bt.NewConnection()
+ Expect(err).ShouldNot(HaveOccurred())
+ })
+
+ AfterEach(func() {
+ s.Kill()
+ bt.cleanup()
+ })
+
+ It("can run top in container", func() {
+ name := "TopAttachTest"
+ id, err := bt.RunTopContainer(&name, nil, nil)
+ Expect(err).ShouldNot(HaveOccurred())
+
+ tickTock := time.NewTimer(2 * time.Second)
+ go func() {
+ <-tickTock.C
+ timeout := uint(5)
+ err := containers.Stop(bt.conn, id, &timeout)
+ if err != nil {
+ GinkgoWriter.Write([]byte(err.Error()))
+ }
+ }()
+
+ stdout := &bytes.Buffer{}
+ stderr := &bytes.Buffer{}
+ go func() {
+ defer GinkgoRecover()
+
+ err := containers.Attach(bt.conn, id, nil, bindings.PTrue, bindings.PTrue, nil, stdout, stderr, nil)
+ Expect(err).ShouldNot(HaveOccurred())
+ }()
+
+ time.Sleep(5 * time.Second)
+
+ // First character/First line of top output
+ Expect(stdout.String()).Should(ContainSubstring("Mem: "))
+ })
+
+ It("can echo data via cat in container", func() {
+ s := specgen.NewSpecGenerator(alpine.name, false)
+ s.Name = "CatAttachTest"
+ s.Terminal = true
+ s.Command = []string{"/bin/cat"}
+ ctnr, err := containers.CreateWithSpec(bt.conn, s)
+ Expect(err).ShouldNot(HaveOccurred())
+
+ err = containers.Start(bt.conn, ctnr.ID, nil)
+ Expect(err).ShouldNot(HaveOccurred())
+
+ wait := define.ContainerStateRunning
+ _, err = containers.Wait(bt.conn, ctnr.ID, &wait)
+ Expect(err).ShouldNot(HaveOccurred())
+
+ tickTock := time.NewTimer(2 * time.Second)
+ go func() {
+ <-tickTock.C
+ timeout := uint(5)
+ err := containers.Stop(bt.conn, ctnr.ID, &timeout)
+ if err != nil {
+ GinkgoWriter.Write([]byte(err.Error()))
+ }
+ }()
+
+ msg := "Hello, World"
+ stdin := &bytes.Buffer{}
+ stdin.WriteString(msg + "\n")
+
+ stdout := &bytes.Buffer{}
+ stderr := &bytes.Buffer{}
+ go func() {
+ defer GinkgoRecover()
+
+ err := containers.Attach(bt.conn, ctnr.ID, nil, bindings.PFalse, bindings.PTrue, stdin, stdout, stderr, nil)
+ Expect(err).ShouldNot(HaveOccurred())
+ }()
+
+ time.Sleep(5 * time.Second)
+ // Tty==true so we get echo'ed stdin + expected output
+ Expect(stdout.String()).Should(Equal(fmt.Sprintf("%[1]s\r\n%[1]s\r\n", msg)))
+ Expect(stderr.String()).Should(BeEmpty())
+ })
+})
diff --git a/pkg/bindings/test/auth_test.go b/pkg/bindings/test/auth_test.go
new file mode 100644
index 000000000..fdb190551
--- /dev/null
+++ b/pkg/bindings/test/auth_test.go
@@ -0,0 +1,143 @@
+package test_bindings
+
+import (
+ "io/ioutil"
+ "os"
+ "time"
+
+ "github.com/containers/common/pkg/auth"
+ "github.com/containers/image/v5/types"
+ podmanRegistry "github.com/containers/libpod/hack/podman-registry-go"
+ "github.com/containers/libpod/pkg/bindings/images"
+ "github.com/containers/libpod/pkg/domain/entities"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("Podman images", func() {
+ var (
+ registry *podmanRegistry.Registry
+ bt *bindingTest
+ s *gexec.Session
+ err error
+ )
+
+ BeforeEach(func() {
+ // Note: we need to start the registry **before** setting up
+ // the test. Otherwise, the registry is not reachable for
+ // currently unknown reasons.
+ registry, err = podmanRegistry.Start()
+ Expect(err).To(BeNil())
+
+ bt = newBindingTest()
+ bt.RestoreImagesFromCache()
+ s = bt.startAPIService()
+ time.Sleep(1 * time.Second)
+ err := bt.NewConnection()
+ Expect(err).To(BeNil())
+ })
+
+ AfterEach(func() {
+ s.Kill()
+ bt.cleanup()
+ registry.Stop()
+ })
+
+ // Test using credentials.
+ It("tag + push + pull (with credentials)", func() {
+
+ imageRep := "localhost:" + registry.Port + "/test"
+ imageTag := "latest"
+ imageRef := imageRep + ":" + imageTag
+
+ // Tag the alpine image and verify it has worked.
+ err = images.Tag(bt.conn, alpine.shortName, imageTag, imageRep)
+ Expect(err).To(BeNil())
+ _, err = images.GetImage(bt.conn, imageRef, nil)
+ Expect(err).To(BeNil())
+
+ // Now push the image.
+ pushOpts := entities.ImagePushOptions{
+ Username: registry.User,
+ Password: registry.Password,
+ SkipTLSVerify: types.OptionalBoolTrue,
+ }
+ err = images.Push(bt.conn, imageRef, imageRef, pushOpts)
+ Expect(err).To(BeNil())
+
+ // Now pull the image.
+ pullOpts := entities.ImagePullOptions{
+ Username: registry.User,
+ Password: registry.Password,
+ SkipTLSVerify: types.OptionalBoolTrue,
+ }
+ _, err = images.Pull(bt.conn, imageRef, pullOpts)
+ Expect(err).To(BeNil())
+ })
+
+ // Test using authfile.
+ It("tag + push + pull + search (with authfile)", func() {
+
+ imageRep := "localhost:" + registry.Port + "/test"
+ imageTag := "latest"
+ imageRef := imageRep + ":" + imageTag
+
+ // Create a temporary authentication file.
+ tmpFile, err := ioutil.TempFile("", "auth.json.")
+ Expect(err).To(BeNil())
+ _, err = tmpFile.Write([]byte{'{', '}'})
+ Expect(err).To(BeNil())
+ err = tmpFile.Close()
+ Expect(err).To(BeNil())
+
+ authFilePath := tmpFile.Name()
+
+ // Now login to a) test the credentials and to b) store them in
+ // the authfile for later use.
+ sys := types.SystemContext{
+ AuthFilePath: authFilePath,
+ DockerInsecureSkipTLSVerify: types.OptionalBoolTrue,
+ }
+ loginOptions := auth.LoginOptions{
+ Username: registry.User,
+ Password: registry.Password,
+ AuthFile: authFilePath,
+ Stdin: os.Stdin,
+ Stdout: os.Stdout,
+ }
+ err = auth.Login(bt.conn, &sys, &loginOptions, []string{imageRep})
+ Expect(err).To(BeNil())
+
+ // Tag the alpine image and verify it has worked.
+ err = images.Tag(bt.conn, alpine.shortName, imageTag, imageRep)
+ Expect(err).To(BeNil())
+ _, err = images.GetImage(bt.conn, imageRef, nil)
+ Expect(err).To(BeNil())
+
+ // Now push the image.
+ pushOpts := entities.ImagePushOptions{
+ Authfile: authFilePath,
+ SkipTLSVerify: types.OptionalBoolTrue,
+ }
+ err = images.Push(bt.conn, imageRef, imageRef, pushOpts)
+ Expect(err).To(BeNil())
+
+ // Now pull the image.
+ pullOpts := entities.ImagePullOptions{
+ Authfile: authFilePath,
+ SkipTLSVerify: types.OptionalBoolTrue,
+ }
+ _, err = images.Pull(bt.conn, imageRef, pullOpts)
+ Expect(err).To(BeNil())
+
+ // Last, but not least, exercise search.
+ searchOptions := entities.ImageSearchOptions{
+ Authfile: authFilePath,
+ SkipTLSVerify: types.OptionalBoolTrue,
+ }
+ _, err = images.Search(bt.conn, imageRef, searchOptions)
+ Expect(err).To(BeNil())
+ })
+
+})
diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go
index f33e42440..a86e6f2e3 100644
--- a/pkg/bindings/test/common_test.go
+++ b/pkg/bindings/test/common_test.go
@@ -191,7 +191,7 @@ func (b *bindingTest) restoreImageFromCache(i testImage) {
func (b *bindingTest) RunTopContainer(containerName *string, insidePod *bool, podName *string) (string, error) {
s := specgen.NewSpecGenerator(alpine.name, false)
s.Terminal = false
- s.Command = []string{"top"}
+ s.Command = []string{"/usr/bin/top"}
if containerName != nil {
s.Name = *containerName
}
diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go
index c79d89b73..3b94b10eb 100644
--- a/pkg/bindings/test/containers_test.go
+++ b/pkg/bindings/test/containers_test.go
@@ -56,7 +56,7 @@ var _ = Describe("Podman containers ", func() {
It("podman pause a running container by name", func() {
// Pausing by name should work
var name = "top"
- _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Pause(bt.conn, name)
Expect(err).To(BeNil())
@@ -70,7 +70,7 @@ var _ = Describe("Podman containers ", func() {
It("podman pause a running container by id", func() {
// Pausing by id should work
var name = "top"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Pause(bt.conn, cid)
Expect(err).To(BeNil())
@@ -84,7 +84,7 @@ var _ = Describe("Podman containers ", func() {
It("podman unpause a running container by name", func() {
// Unpausing by name should work
var name = "top"
- _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Pause(bt.conn, name)
Expect(err).To(BeNil())
@@ -100,7 +100,7 @@ var _ = Describe("Podman containers ", func() {
It("podman unpause a running container by ID", func() {
// Unpausing by ID should work
var name = "top"
- _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
// Pause by name
err = containers.Pause(bt.conn, name)
@@ -119,7 +119,7 @@ var _ = Describe("Podman containers ", func() {
It("podman pause a paused container by name", func() {
// Pausing a paused container by name should fail
var name = "top"
- _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Pause(bt.conn, name)
Expect(err).To(BeNil())
@@ -132,7 +132,7 @@ var _ = Describe("Podman containers ", func() {
It("podman pause a paused container by id", func() {
// Pausing a paused container by id should fail
var name = "top"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Pause(bt.conn, cid)
Expect(err).To(BeNil())
@@ -145,7 +145,7 @@ var _ = Describe("Podman containers ", func() {
It("podman pause a stopped container by name", func() {
// Pausing a stopped container by name should fail
var name = "top"
- _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Stop(bt.conn, name, nil)
Expect(err).To(BeNil())
@@ -158,7 +158,7 @@ var _ = Describe("Podman containers ", func() {
It("podman pause a stopped container by id", func() {
// Pausing a stopped container by id should fail
var name = "top"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Stop(bt.conn, cid, nil)
Expect(err).To(BeNil())
@@ -171,11 +171,11 @@ var _ = Describe("Podman containers ", func() {
It("podman remove a paused container by id without force", func() {
// Removing a paused container without force should fail
var name = "top"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Pause(bt.conn, cid)
Expect(err).To(BeNil())
- err = containers.Remove(bt.conn, cid, &bindings.PFalse, &bindings.PFalse)
+ err = containers.Remove(bt.conn, cid, bindings.PFalse, bindings.PFalse)
Expect(err).ToNot(BeNil())
code, _ := bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
@@ -192,18 +192,18 @@ var _ = Describe("Podman containers ", func() {
// Removing a paused container with force should work
var name = "top"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Pause(bt.conn, cid)
Expect(err).To(BeNil())
- err = containers.Remove(bt.conn, cid, &bindings.PTrue, &bindings.PFalse)
+ err = containers.Remove(bt.conn, cid, bindings.PTrue, bindings.PFalse)
Expect(err).To(BeNil())
})
It("podman stop a paused container by name", func() {
// Stopping a paused container by name should fail
var name = "top"
- _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Pause(bt.conn, name)
Expect(err).To(BeNil())
@@ -216,7 +216,7 @@ var _ = Describe("Podman containers ", func() {
It("podman stop a paused container by id", func() {
// Stopping a paused container by id should fail
var name = "top"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Pause(bt.conn, cid)
Expect(err).To(BeNil())
@@ -229,7 +229,7 @@ var _ = Describe("Podman containers ", func() {
It("podman stop a running container by name", func() {
// Stopping a running container by name should work
var name = "top"
- _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Stop(bt.conn, name, nil)
Expect(err).To(BeNil())
@@ -243,7 +243,7 @@ var _ = Describe("Podman containers ", func() {
It("podman stop a running container by ID", func() {
// Stopping a running container by ID should work
var name = "top"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Stop(bt.conn, cid, nil)
Expect(err).To(BeNil())
@@ -302,6 +302,8 @@ var _ = Describe("Podman containers ", func() {
errChan = make(chan error)
go func() {
+ defer GinkgoRecover()
+
_, waitErr := containers.Wait(bt.conn, name, &running)
errChan <- waitErr
close(errChan)
@@ -324,7 +326,7 @@ var _ = Describe("Podman containers ", func() {
// a container that has no healthcheck should be a 409
var name = "top"
- bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ bt.RunTopContainer(&name, bindings.PFalse, nil)
_, err = containers.RunHealthCheck(bt.conn, name)
Expect(err).ToNot(BeNil())
code, _ = bindings.CheckResponseCode(err)
@@ -371,19 +373,19 @@ var _ = Describe("Podman containers ", func() {
_, err = containers.Wait(bt.conn, r.ID, nil)
Expect(err).To(BeNil())
- opts := containers.LogOptions{Stdout: &bindings.PTrue, Follow: &bindings.PTrue}
+ opts := containers.LogOptions{Stdout: bindings.PTrue, Follow: bindings.PTrue}
go func() {
containers.Logs(bt.conn, r.ID, opts, stdoutChan, nil)
}()
o := <-stdoutChan
- o = strings.ReplaceAll(o, "\r", "")
+ o = strings.TrimSpace(o)
_, err = time.Parse(time.RFC1123Z, o)
- Expect(err).To(BeNil())
+ Expect(err).ShouldNot(HaveOccurred())
})
It("podman top", func() {
var name = "top"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
// By name
@@ -421,7 +423,7 @@ var _ = Describe("Podman containers ", func() {
It("podman container exists in local storage by name", func() {
// Container existence check by name should work
var name = "top"
- _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
containerExists, err := containers.Exists(bt.conn, name)
Expect(err).To(BeNil())
@@ -431,7 +433,7 @@ var _ = Describe("Podman containers ", func() {
It("podman container exists in local storage by ID", func() {
// Container existence check by ID should work
var name = "top"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
containerExists, err := containers.Exists(bt.conn, cid)
Expect(err).To(BeNil())
@@ -441,7 +443,7 @@ var _ = Describe("Podman containers ", func() {
It("podman container exists in local storage by short ID", func() {
// Container existence check by short ID should work
var name = "top"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
containerExists, err := containers.Exists(bt.conn, cid[0:12])
Expect(err).To(BeNil())
@@ -459,7 +461,7 @@ var _ = Describe("Podman containers ", func() {
It("podman kill a running container by name with SIGINT", func() {
// Killing a running container should work
var name = "top"
- _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Kill(bt.conn, name, "SIGINT")
Expect(err).To(BeNil())
@@ -470,7 +472,7 @@ var _ = Describe("Podman containers ", func() {
It("podman kill a running container by ID with SIGTERM", func() {
// Killing a running container by ID should work
var name = "top"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Kill(bt.conn, cid, "SIGTERM")
Expect(err).To(BeNil())
@@ -481,7 +483,7 @@ var _ = Describe("Podman containers ", func() {
It("podman kill a running container by ID with SIGKILL", func() {
// Killing a running container by ID with TERM should work
var name = "top"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Kill(bt.conn, cid, "SIGKILL")
Expect(err).To(BeNil())
@@ -490,7 +492,7 @@ var _ = Describe("Podman containers ", func() {
It("podman kill a running container by bogus signal", func() {
//Killing a running container by bogus signal should fail
var name = "top"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Kill(bt.conn, cid, "foobar")
Expect(err).ToNot(BeNil())
@@ -503,9 +505,9 @@ var _ = Describe("Podman containers ", func() {
var name1 = "first"
var name2 = "second"
var latestContainers = 1
- _, err := bt.RunTopContainer(&name1, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name1, bindings.PFalse, nil)
Expect(err).To(BeNil())
- _, err = bt.RunTopContainer(&name2, &bindings.PFalse, nil)
+ _, err = bt.RunTopContainer(&name2, bindings.PFalse, nil)
Expect(err).To(BeNil())
containerLatestList, err := containers.List(bt.conn, nil, nil, &latestContainers, nil, nil, nil)
Expect(err).To(BeNil())
@@ -531,10 +533,10 @@ var _ = Describe("Podman containers ", func() {
Expect(err).ToNot(BeNil())
})
- It("podman prune stoped containers", func() {
+ It("podman prune stopped containers", func() {
// Start and stop a container to enter in exited state.
var name = "top"
- _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Stop(bt.conn, name, nil)
Expect(err).To(BeNil())
@@ -546,10 +548,10 @@ var _ = Describe("Podman containers ", func() {
Expect(len(pruneResponse.ID)).To(Equal(1))
})
- It("podman prune stoped containers with filters", func() {
+ It("podman prune stopped containers with filters", func() {
// Start and stop a container to enter in exited state.
var name = "top"
- _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Stop(bt.conn, name, nil)
Expect(err).To(BeNil())
@@ -583,7 +585,7 @@ var _ = Describe("Podman containers ", func() {
It("podman prune running containers", func() {
// Start the container.
var name = "top"
- _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
// Check if the container is running.
@@ -596,4 +598,145 @@ var _ = Describe("Podman containers ", func() {
Expect(err).To(BeNil())
Expect(len(pruneResponse.ID)).To(Equal(0))
})
+
+ It("podman inspect bogus container", func() {
+ _, err := containers.Inspect(bt.conn, "foobar", nil)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusNotFound))
+ })
+
+ It("podman inspect running container", func() {
+ var name = "top"
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ // Inspecting running container should succeed
+ _, err = containers.Inspect(bt.conn, name, nil)
+ Expect(err).To(BeNil())
+ })
+
+ It("podman inspect stopped container", func() {
+ var name = "top"
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ err = containers.Stop(bt.conn, name, nil)
+ Expect(err).To(BeNil())
+ // Inspecting stopped container should succeed
+ _, err = containers.Inspect(bt.conn, name, nil)
+ Expect(err).To(BeNil())
+ })
+
+ It("podman inspect running container with size", func() {
+ var name = "top"
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ _, err = containers.Inspect(bt.conn, name, bindings.PTrue)
+ Expect(err).To(BeNil())
+ })
+
+ It("podman inspect stopped container with size", func() {
+ var name = "top"
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ err = containers.Stop(bt.conn, name, nil)
+ Expect(err).To(BeNil())
+ // Inspecting stopped container with size should succeed
+ _, err = containers.Inspect(bt.conn, name, bindings.PTrue)
+ Expect(err).To(BeNil())
+ })
+
+ It("podman remove bogus container", func() {
+ err = containers.Remove(bt.conn, "foobar", nil, nil)
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusNotFound))
+ })
+
+ It("podman remove running container by name", func() {
+ var name = "top"
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ // Removing running container should fail
+ err = containers.Remove(bt.conn, name, nil, nil)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman remove running container by ID", func() {
+ var name = "top"
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ // Removing running container should fail
+ err = containers.Remove(bt.conn, cid, nil, nil)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman forcibly remove running container by name", func() {
+ var name = "top"
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ // Removing running container should fail
+ err = containers.Remove(bt.conn, name, bindings.PTrue, nil)
+ Expect(err).To(BeNil())
+ //code, _ := bindings.CheckResponseCode(err)
+ //Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman forcibly remove running container by ID", func() {
+ var name = "top"
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ // Removing running container should fail
+ err = containers.Remove(bt.conn, cid, bindings.PTrue, nil)
+ Expect(err).To(BeNil())
+ //code, _ := bindings.CheckResponseCode(err)
+ //Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman remove running container and volume by name", func() {
+ var name = "top"
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ // Removing running container should fail
+ err = containers.Remove(bt.conn, name, nil, bindings.PTrue)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman remove running container and volume by ID", func() {
+ var name = "top"
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ // Removing running container should fail
+ err = containers.Remove(bt.conn, cid, nil, bindings.PTrue)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman forcibly remove running container and volume by name", func() {
+ var name = "top"
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ // Removing running container should fail
+ err = containers.Remove(bt.conn, name, bindings.PTrue, bindings.PTrue)
+ Expect(err).To(BeNil())
+ //code, _ := bindings.CheckResponseCode(err)
+ //Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman forcibly remove running container and volume by ID", func() {
+ var name = "top"
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ // Removing running container should fail
+ err = containers.Remove(bt.conn, cid, bindings.PTrue, bindings.PTrue)
+ Expect(err).To(BeNil())
+ //code, _ := bindings.CheckResponseCode(err)
+ //Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
})
diff --git a/pkg/bindings/test/exec_test.go b/pkg/bindings/test/exec_test.go
index 1ef2197b6..53b2dcb4a 100644
--- a/pkg/bindings/test/exec_test.go
+++ b/pkg/bindings/test/exec_test.go
@@ -33,7 +33,7 @@ var _ = Describe("Podman containers exec", func() {
It("Podman exec create makes an exec session", func() {
name := "testCtr"
- cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
execConfig := new(handlers.ExecCreateConfig)
@@ -53,7 +53,7 @@ var _ = Describe("Podman containers exec", func() {
It("Podman exec create with bad command fails", func() {
name := "testCtr"
- _, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
execConfig := new(handlers.ExecCreateConfig)
diff --git a/pkg/bindings/test/images_test.go b/pkg/bindings/test/images_test.go
index 58210efd0..f2a1a51e5 100644
--- a/pkg/bindings/test/images_test.go
+++ b/pkg/bindings/test/images_test.go
@@ -76,7 +76,7 @@ var _ = Describe("Podman images", func() {
// Expect(data.Size).To(BeZero())
// Enabling the size parameter should result in size being populated
- data, err = images.GetImage(bt.conn, alpine.name, &bindings.PTrue)
+ data, err = images.GetImage(bt.conn, alpine.name, bindings.PTrue)
Expect(err).To(BeNil())
Expect(data.Size).To(BeNumerically(">", 0))
})
@@ -84,50 +84,54 @@ var _ = Describe("Podman images", func() {
// Test to validate the remove image api
It("remove image", func() {
// Remove invalid image should be a 404
- _, err = images.Remove(bt.conn, "foobar5000", &bindings.PFalse)
+ response, err := images.Remove(bt.conn, "foobar5000", false)
Expect(err).ToNot(BeNil())
+ Expect(response).To(BeNil())
code, _ := bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusNotFound))
// Remove an image by name, validate image is removed and error is nil
inspectData, err := images.GetImage(bt.conn, busybox.shortName, nil)
Expect(err).To(BeNil())
- response, err := images.Remove(bt.conn, busybox.shortName, nil)
+ response, err = images.Remove(bt.conn, busybox.shortName, false)
Expect(err).To(BeNil())
- Expect(inspectData.ID).To(Equal(response[0]["Deleted"]))
+ code, _ = bindings.CheckResponseCode(err)
+
+ Expect(inspectData.ID).To(Equal(response.Deleted[0]))
inspectData, err = images.GetImage(bt.conn, busybox.shortName, nil)
code, _ = bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusNotFound))
// Start a container with alpine image
var top string = "top"
- _, err = bt.RunTopContainer(&top, &bindings.PFalse, nil)
+ _, err = bt.RunTopContainer(&top, bindings.PFalse, nil)
Expect(err).To(BeNil())
// we should now have a container called "top" running
- containerResponse, err := containers.Inspect(bt.conn, "top", &bindings.PFalse)
+ containerResponse, err := containers.Inspect(bt.conn, "top", nil)
Expect(err).To(BeNil())
Expect(containerResponse.Name).To(Equal("top"))
// try to remove the image "alpine". This should fail since we are not force
// deleting hence image cannot be deleted until the container is deleted.
- response, err = images.Remove(bt.conn, alpine.shortName, &bindings.PFalse)
+ response, err = images.Remove(bt.conn, alpine.shortName, false)
code, _ = bindings.CheckResponseCode(err)
- Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ Expect(code).To(BeNumerically("==", http.StatusConflict))
// Removing the image "alpine" where force = true
- response, err = images.Remove(bt.conn, alpine.shortName, &bindings.PTrue)
+ response, err = images.Remove(bt.conn, alpine.shortName, true)
Expect(err).To(BeNil())
-
- // Checking if both the images are gone as well as the container is deleted
- inspectData, err = images.GetImage(bt.conn, busybox.shortName, nil)
+ // To be extra sure, check if the previously created container
+ // is gone as well.
+ _, err = containers.Inspect(bt.conn, "top", bindings.PFalse)
code, _ = bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusNotFound))
- inspectData, err = images.GetImage(bt.conn, alpine.shortName, nil)
+ // Now make sure both images are gone.
+ inspectData, err = images.GetImage(bt.conn, busybox.shortName, nil)
code, _ = bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusNotFound))
- _, err = containers.Inspect(bt.conn, "top", &bindings.PFalse)
+ inspectData, err = images.GetImage(bt.conn, alpine.shortName, nil)
code, _ = bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusNotFound))
})
@@ -178,13 +182,13 @@ var _ = Describe("Podman images", func() {
// List images with a filter
filters := make(map[string][]string)
filters["reference"] = []string{alpine.name}
- filteredImages, err := images.List(bt.conn, &bindings.PFalse, filters)
+ filteredImages, err := images.List(bt.conn, bindings.PFalse, filters)
Expect(err).To(BeNil())
Expect(len(filteredImages)).To(BeNumerically("==", 1))
// List images with a bad filter
filters["name"] = []string{alpine.name}
- _, err = images.List(bt.conn, &bindings.PFalse, filters)
+ _, err = images.List(bt.conn, bindings.PFalse, filters)
Expect(err).ToNot(BeNil())
code, _ := bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
@@ -209,7 +213,7 @@ var _ = Describe("Podman images", func() {
It("Load|Import Image", func() {
// load an image
- _, err := images.Remove(bt.conn, alpine.name, nil)
+ _, err := images.Remove(bt.conn, alpine.name, false)
Expect(err).To(BeNil())
exists, err := images.Exists(bt.conn, alpine.name)
Expect(err).To(BeNil())
@@ -219,7 +223,7 @@ var _ = Describe("Podman images", func() {
Expect(err).To(BeNil())
names, err := images.Load(bt.conn, f, nil)
Expect(err).To(BeNil())
- Expect(names.Name).To(Equal(alpine.name))
+ Expect(names.Names[0]).To(Equal(alpine.name))
exists, err = images.Exists(bt.conn, alpine.name)
Expect(err).To(BeNil())
Expect(exists).To(BeTrue())
@@ -227,7 +231,7 @@ var _ = Describe("Podman images", func() {
// load with a repo name
f, err = os.Open(filepath.Join(ImageCacheDir, alpine.tarballName))
Expect(err).To(BeNil())
- _, err = images.Remove(bt.conn, alpine.name, nil)
+ _, err = images.Remove(bt.conn, alpine.name, false)
Expect(err).To(BeNil())
exists, err = images.Exists(bt.conn, alpine.name)
Expect(err).To(BeNil())
@@ -235,7 +239,7 @@ var _ = Describe("Podman images", func() {
newName := "quay.io/newname:fizzle"
names, err = images.Load(bt.conn, f, &newName)
Expect(err).To(BeNil())
- Expect(names.Name).To(Equal(alpine.name))
+ Expect(names.Names[0]).To(Equal(alpine.name))
exists, err = images.Exists(bt.conn, newName)
Expect(err).To(BeNil())
Expect(exists).To(BeTrue())
@@ -243,7 +247,7 @@ var _ = Describe("Podman images", func() {
// load with a bad repo name should trigger a 500
f, err = os.Open(filepath.Join(ImageCacheDir, alpine.tarballName))
Expect(err).To(BeNil())
- _, err = images.Remove(bt.conn, alpine.name, nil)
+ _, err = images.Remove(bt.conn, alpine.name, false)
Expect(err).To(BeNil())
exists, err = images.Exists(bt.conn, alpine.name)
Expect(err).To(BeNil())
@@ -271,7 +275,7 @@ var _ = Describe("Podman images", func() {
It("Import Image", func() {
// load an image
- _, err = images.Remove(bt.conn, alpine.name, nil)
+ _, err = images.Remove(bt.conn, alpine.name, false)
Expect(err).To(BeNil())
exists, err := images.Exists(bt.conn, alpine.name)
Expect(err).To(BeNil())
diff --git a/pkg/bindings/test/manifests_test.go b/pkg/bindings/test/manifests_test.go
index 23c3d8194..71d626b7b 100644
--- a/pkg/bindings/test/manifests_test.go
+++ b/pkg/bindings/test/manifests_test.go
@@ -47,7 +47,7 @@ var _ = Describe("Podman containers ", func() {
code, _ := bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
- _, err = images.Remove(bt.conn, id, nil)
+ _, err = images.Remove(bt.conn, id, false)
Expect(err).To(BeNil())
// create manifest list with images
@@ -118,6 +118,28 @@ var _ = Describe("Podman containers ", func() {
Expect(len(data.Manifests)).To(BeZero())
})
+ // There is NO annotate endpoint, this could never work.:w
+
+ //It("annotate manifest", func() {
+ // id, err := manifests.Create(bt.conn, []string{"quay.io/libpod/foobar:latest"}, []string{}, nil)
+ // Expect(err).To(BeNil())
+ // opts := image.ManifestAddOpts{Images: []string{"docker.io/library/alpine:latest"}}
+ //
+ // _, err = manifests.Add(bt.conn, id, opts)
+ // Expect(err).To(BeNil())
+ // data, err := manifests.Inspect(bt.conn, id)
+ // Expect(err).To(BeNil())
+ // Expect(len(data.Manifests)).To(BeNumerically("==", 1))
+ // digest := data.Manifests[0].Digest.String()
+ // annoOpts := image.ManifestAnnotateOpts{OS: "foo"}
+ // _, err = manifests.Annotate(bt.conn, id, digest, annoOpts)
+ // Expect(err).To(BeNil())
+ // list, err := manifests.Inspect(bt.conn, id)
+ // Expect(err).To(BeNil())
+ // Expect(len(list.Manifests)).To(BeNumerically("==", 1))
+ // Expect(list.Manifests[0].Platform.OS).To(Equal("foo"))
+ //})
+
It("push manifest", func() {
Skip("TODO")
})
diff --git a/pkg/bindings/test/pods_test.go b/pkg/bindings/test/pods_test.go
index 8a0b9c7a6..d8e2a5ef7 100644
--- a/pkg/bindings/test/pods_test.go
+++ b/pkg/bindings/test/pods_test.go
@@ -57,8 +57,13 @@ var _ = Describe("Podman pods", func() {
podSummary, err := pods.List(bt.conn, nil)
Expect(err).To(BeNil())
Expect(len(podSummary)).To(Equal(1))
+
+ // Start the pod
+ _, err = pods.Start(bt.conn, newpod)
+ Expect(err).To(BeNil())
+
// Adding an alpine container to the existing pod
- _, err = bt.RunTopContainer(nil, &bindings.PTrue, &newpod)
+ _, err = bt.RunTopContainer(nil, bindings.PTrue, &newpod)
Expect(err).To(BeNil())
podSummary, err = pods.List(bt.conn, nil)
// Verify no errors.
@@ -83,7 +88,12 @@ var _ = Describe("Podman pods", func() {
It("List pods with filters", func() {
newpod2 := "newpod2"
bt.Podcreate(&newpod2)
- _, err = bt.RunTopContainer(nil, &bindings.PTrue, &newpod)
+
+ // Start the pod
+ _, err = pods.Start(bt.conn, newpod)
+ Expect(err).To(BeNil())
+
+ _, err = bt.RunTopContainer(nil, bindings.PTrue, &newpod)
Expect(err).To(BeNil())
// Expected err with invalid filter params
@@ -164,7 +174,7 @@ var _ = Describe("Podman pods", func() {
Expect(code).To(BeNumerically("==", http.StatusNotFound))
// Adding an alpine container to the existing pod
- _, err = bt.RunTopContainer(nil, &bindings.PTrue, &newpod)
+ _, err = bt.RunTopContainer(nil, bindings.PTrue, &newpod)
Expect(err).To(BeNil())
// Binding needs to be modified to inspect the pod state.
diff --git a/pkg/bindings/test/system_test.go b/pkg/bindings/test/system_test.go
index 87e6d56dc..dd3778754 100644
--- a/pkg/bindings/test/system_test.go
+++ b/pkg/bindings/test/system_test.go
@@ -3,7 +3,6 @@ package test_bindings
import (
"time"
- "github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/bindings/containers"
"github.com/containers/libpod/pkg/bindings/pods"
@@ -39,8 +38,8 @@ var _ = Describe("Podman system", func() {
})
It("podman events", func() {
- eChan := make(chan handlers.Event, 1)
- var messages []handlers.Event
+ eChan := make(chan entities.Event, 1)
+ var messages []entities.Event
cancelChan := make(chan bool, 1)
go func() {
for e := range eChan {
@@ -48,13 +47,13 @@ var _ = Describe("Podman system", func() {
}
}()
go func() {
- system.Events(bt.conn, eChan, cancelChan, nil, nil, nil)
+ system.Events(bt.conn, eChan, cancelChan, nil, nil, nil, bindings.PFalse)
}()
_, err := bt.RunTopContainer(nil, nil, nil)
Expect(err).To(BeNil())
cancelChan <- true
- Expect(len(messages)).To(BeNumerically("==", 3))
+ Expect(len(messages)).To(BeNumerically("==", 5))
})
It("podman system prune - pod,container stopped", func() {
@@ -65,12 +64,12 @@ var _ = Describe("Podman system", func() {
Expect(err).To(BeNil())
// Start and stop a container to enter in exited state.
var name = "top"
- _, err = bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err = bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Stop(bt.conn, name, nil)
Expect(err).To(BeNil())
- systemPruneResponse, err := system.Prune(bt.conn, &bindings.PTrue, &bindings.PFalse)
+ systemPruneResponse, err := system.Prune(bt.conn, bindings.PTrue, bindings.PFalse)
Expect(err).To(BeNil())
Expect(len(systemPruneResponse.PodPruneReport)).To(Equal(1))
Expect(len(systemPruneResponse.ContainerPruneReport.ID)).To(Equal(1))
@@ -90,21 +89,21 @@ var _ = Describe("Podman system", func() {
// Start and stop a container to enter in exited state.
var name = "top"
- _, err = bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err = bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Stop(bt.conn, name, nil)
Expect(err).To(BeNil())
// Start container and leave in running
var name2 = "top2"
- _, err = bt.RunTopContainer(&name2, &bindings.PFalse, nil)
+ _, err = bt.RunTopContainer(&name2, bindings.PFalse, nil)
Expect(err).To(BeNil())
// Adding an unused volume
_, err = volumes.Create(bt.conn, entities.VolumeCreateOptions{})
Expect(err).To(BeNil())
- systemPruneResponse, err := system.Prune(bt.conn, &bindings.PTrue, &bindings.PFalse)
+ systemPruneResponse, err := system.Prune(bt.conn, bindings.PTrue, bindings.PFalse)
Expect(err).To(BeNil())
Expect(len(systemPruneResponse.PodPruneReport)).To(Equal(1))
Expect(len(systemPruneResponse.ContainerPruneReport.ID)).To(Equal(1))
@@ -124,21 +123,21 @@ var _ = Describe("Podman system", func() {
// Start and stop a container to enter in exited state.
var name = "top"
- _, err = bt.RunTopContainer(&name, &bindings.PFalse, nil)
+ _, err = bt.RunTopContainer(&name, bindings.PFalse, nil)
Expect(err).To(BeNil())
err = containers.Stop(bt.conn, name, nil)
Expect(err).To(BeNil())
// Start second container and leave in running
var name2 = "top2"
- _, err = bt.RunTopContainer(&name2, &bindings.PFalse, nil)
+ _, err = bt.RunTopContainer(&name2, bindings.PFalse, nil)
Expect(err).To(BeNil())
// Adding an unused volume should work
_, err = volumes.Create(bt.conn, entities.VolumeCreateOptions{})
Expect(err).To(BeNil())
- systemPruneResponse, err := system.Prune(bt.conn, &bindings.PTrue, &bindings.PTrue)
+ systemPruneResponse, err := system.Prune(bt.conn, bindings.PTrue, bindings.PTrue)
Expect(err).To(BeNil())
Expect(len(systemPruneResponse.PodPruneReport)).To(Equal(0))
Expect(len(systemPruneResponse.ContainerPruneReport.ID)).To(Equal(1))
diff --git a/pkg/bindings/test/test_suite_test.go b/pkg/bindings/test/test_suite_test.go
index dc2b49b88..d2c2c7838 100644
--- a/pkg/bindings/test/test_suite_test.go
+++ b/pkg/bindings/test/test_suite_test.go
@@ -5,9 +5,14 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
+ "github.com/sirupsen/logrus"
)
func TestTest(t *testing.T) {
+ if testing.Verbose() {
+ logrus.SetLevel(logrus.DebugLevel)
+ }
+
RegisterFailHandler(Fail)
RunSpecs(t, "Test Suite")
}
diff --git a/pkg/bindings/test/volumes_test.go b/pkg/bindings/test/volumes_test.go
index 59fe48f22..839a4c575 100644
--- a/pkg/bindings/test/volumes_test.go
+++ b/pkg/bindings/test/volumes_test.go
@@ -105,7 +105,7 @@ var _ = Describe("Podman volumes", func() {
zero := uint(0)
err = containers.Stop(connText, "vtest", &zero)
Expect(err).To(BeNil())
- err = volumes.Remove(connText, vol.Name, &bindings.PTrue)
+ err = volumes.Remove(connText, vol.Name, bindings.PTrue)
Expect(err).To(BeNil())
})
diff --git a/pkg/bindings/version.go b/pkg/bindings/version.go
deleted file mode 100644
index c833a644c..000000000
--- a/pkg/bindings/version.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package bindings
-
-func (c Connection) Version() {}
diff --git a/pkg/bindings/volumes/volumes.go b/pkg/bindings/volumes/volumes.go
index cef9246cb..ebe19794a 100644
--- a/pkg/bindings/volumes/volumes.go
+++ b/pkg/bindings/volumes/volumes.go
@@ -26,7 +26,7 @@ func Create(ctx context.Context, config entities.VolumeCreateOptions) (*entities
return nil, err
}
stringReader := strings.NewReader(createString)
- response, err := conn.DoRequest(stringReader, http.MethodPost, "/volumes/create", nil)
+ response, err := conn.DoRequest(stringReader, http.MethodPost, "/volumes/create", nil, nil)
if err != nil {
return nil, err
}
@@ -42,7 +42,7 @@ func Inspect(ctx context.Context, nameOrID string) (*entities.VolumeConfigRespon
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/volumes/%s/json", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/volumes/%s/json", nil, nil, nameOrID)
if err != nil {
return &inspect, err
}
@@ -67,7 +67,7 @@ func List(ctx context.Context, filters map[string][]string) ([]*entities.VolumeL
}
params.Set("filters", strFilters)
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/volumes/json", params)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/volumes/json", params, nil)
if err != nil {
return vols, err
}
@@ -83,7 +83,7 @@ func Prune(ctx context.Context) ([]*entities.VolumePruneReport, error) {
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/volumes/prune", nil)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/volumes/prune", nil, nil)
if err != nil {
return nil, err
}
@@ -101,7 +101,7 @@ func Remove(ctx context.Context, nameOrID string, force *bool) error {
if force != nil {
params.Set("force", strconv.FormatBool(*force))
}
- response, err := conn.DoRequest(nil, http.MethodDelete, "/volumes/%s", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodDelete, "/volumes/%s", params, nil, nameOrID)
if err != nil {
return err
}