summaryrefslogtreecommitdiff
path: root/pkg/bindings
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/bindings')
-rw-r--r--pkg/bindings/containers/attach.go25
-rw-r--r--pkg/bindings/containers/checkpoint.go9
-rw-r--r--pkg/bindings/containers/term_unix.go25
-rw-r--r--pkg/bindings/containers/term_windows.go69
-rw-r--r--pkg/bindings/containers/types.go23
-rw-r--r--pkg/bindings/containers/types_restore_options.go15
-rw-r--r--pkg/bindings/generator/generator.go1
-rw-r--r--pkg/bindings/images/build_unix.go1
-rw-r--r--pkg/bindings/images/types.go8
-rw-r--r--pkg/bindings/images/types_import_options.go45
-rw-r--r--pkg/bindings/images/types_remove_options.go15
-rw-r--r--pkg/bindings/play/play.go39
-rw-r--r--pkg/bindings/play/types.go2
-rw-r--r--pkg/bindings/play/types_kube_options.go15
-rw-r--r--pkg/bindings/test/attach_test.go3
-rw-r--r--pkg/bindings/test/auth_test.go3
-rw-r--r--pkg/bindings/test/common_test.go2
-rw-r--r--pkg/bindings/test/containers_test.go3
18 files changed, 263 insertions, 40 deletions
diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go
index c6d434c87..0c6ebdd2f 100644
--- a/pkg/bindings/containers/attach.go
+++ b/pkg/bindings/containers/attach.go
@@ -10,14 +10,12 @@ import (
"net/http"
"net/url"
"os"
- "os/signal"
"reflect"
"strconv"
"time"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/bindings"
- sig "github.com/containers/podman/v4/pkg/signal"
"github.com/containers/podman/v4/utils"
"github.com/moby/term"
"github.com/pkg/errors"
@@ -94,7 +92,8 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri
// 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
+ outFile, outOk := stdout.(*os.File)
+ needTTY := ok && outOk && terminal.IsTerminal(int(file.Fd())) && ctnr.Config.Tty
if needTTY {
state, err := setRawTerminal(file)
if err != nil {
@@ -142,11 +141,10 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri
if needTTY {
winChange := make(chan os.Signal, 1)
- signal.Notify(winChange, sig.SIGWINCH)
winCtx, winCancel := context.WithCancel(ctx)
defer winCancel()
-
- attachHandleResize(ctx, winCtx, winChange, false, nameOrID, file)
+ notifyWinChange(winCtx, winChange, file, outFile)
+ attachHandleResize(ctx, winCtx, winChange, false, nameOrID, file, outFile)
}
// If we are attaching around a start, we need to "signal"
@@ -281,7 +279,7 @@ func DemuxFrame(r io.Reader, buffer []byte, length int) (frame []byte, err error
n, err := io.ReadFull(r, buffer[0:length])
if err != nil {
- return nil, nil
+ return nil, err
}
if n < length {
err = io.ErrUnexpectedEOF
@@ -345,9 +343,9 @@ func (f *rawFormatter) Format(entry *logrus.Entry) ([]byte, error) {
// This is intended to not be run as a goroutine, handling resizing for a container
// or exec session. It will call resize once and then starts a goroutine which calls resize on winChange
-func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, isExec bool, id string, file *os.File) {
+func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, isExec bool, id string, file *os.File, outFile *os.File) {
resize := func() {
- w, h, err := terminal.GetSize(int(file.Fd()))
+ w, h, err := getTermSize(file, outFile)
if err != nil {
logrus.Warnf("Failed to obtain TTY size: %v", err)
}
@@ -379,7 +377,7 @@ func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, i
// Configure the given terminal for raw mode
func setRawTerminal(file *os.File) (*terminal.State, error) {
- state, err := terminal.MakeRaw(int(file.Fd()))
+ state, err := makeRawTerm(file)
if err != nil {
return nil, err
}
@@ -402,6 +400,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar
// TODO: Make this configurable (can't use streams' InputStream as it's
// buffered)
terminalFile := os.Stdin
+ terminalOutFile := os.Stdout
logrus.Debugf("Starting & Attaching to exec session ID %q", sessionID)
@@ -447,7 +446,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar
}
logrus.SetFormatter(&logrus.TextFormatter{})
}()
- w, h, err := terminal.GetSize(int(terminalFile.Fd()))
+ w, h, err := getTermSize(terminalFile, terminalOutFile)
if err != nil {
logrus.Warnf("Failed to obtain TTY size: %v", err)
}
@@ -490,11 +489,11 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar
if needTTY {
winChange := make(chan os.Signal, 1)
- signal.Notify(winChange, sig.SIGWINCH)
winCtx, winCancel := context.WithCancel(ctx)
defer winCancel()
- attachHandleResize(ctx, winCtx, winChange, true, sessionID, terminalFile)
+ notifyWinChange(winCtx, winChange, terminalFile, terminalOutFile)
+ attachHandleResize(ctx, winCtx, winChange, true, sessionID, terminalFile, terminalOutFile)
}
if options.GetAttachInput() {
diff --git a/pkg/bindings/containers/checkpoint.go b/pkg/bindings/containers/checkpoint.go
index 1d8c34b33..bcb944488 100644
--- a/pkg/bindings/containers/checkpoint.go
+++ b/pkg/bindings/containers/checkpoint.go
@@ -79,7 +79,14 @@ func Restore(ctx context.Context, nameOrID string, options *RestoreOptions) (*en
// Open the to-be-imported archive if needed.
var r io.Reader
- if i := options.GetImportAchive(); i != "" {
+ i := options.GetImportArchive()
+ if i == "" {
+ // backwards compat, ImportAchive is a typo but we still have to
+ // support this to avoid breaking users
+ // TODO: remove ImportAchive with 5.0
+ i = options.GetImportAchive()
+ }
+ if i != "" {
params.Set("import", "true")
r, err = os.Open(i)
if err != nil {
diff --git a/pkg/bindings/containers/term_unix.go b/pkg/bindings/containers/term_unix.go
new file mode 100644
index 000000000..2c976393f
--- /dev/null
+++ b/pkg/bindings/containers/term_unix.go
@@ -0,0 +1,25 @@
+//go:build !windows
+// +build !windows
+
+package containers
+
+import (
+ "context"
+ "os"
+ "os/signal"
+
+ sig "github.com/containers/podman/v4/pkg/signal"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+func makeRawTerm(stdin *os.File) (*terminal.State, error) {
+ return terminal.MakeRaw(int(stdin.Fd()))
+}
+
+func notifyWinChange(ctx context.Context, winChange chan os.Signal, stdin *os.File, stdout *os.File) {
+ signal.Notify(winChange, sig.SIGWINCH)
+}
+
+func getTermSize(stdin *os.File, stdout *os.File) (width, height int, err error) {
+ return terminal.GetSize(int(stdin.Fd()))
+}
diff --git a/pkg/bindings/containers/term_windows.go b/pkg/bindings/containers/term_windows.go
new file mode 100644
index 000000000..11d4bd50d
--- /dev/null
+++ b/pkg/bindings/containers/term_windows.go
@@ -0,0 +1,69 @@
+package containers
+
+import (
+ "context"
+ "os"
+ "time"
+
+ sig "github.com/containers/podman/v4/pkg/signal"
+ "golang.org/x/crypto/ssh/terminal"
+ "golang.org/x/sys/windows"
+)
+
+func makeRawTerm(stdin *os.File) (*terminal.State, error) {
+ state, err := terminal.MakeRaw(int(stdin.Fd()))
+ if err != nil {
+ return nil, err
+ }
+
+ // Attempt VT if supported (recent versions of Windows 10+)
+ var raw uint32
+ handle := windows.Handle(stdin.Fd())
+ if err := windows.GetConsoleMode(handle, &raw); err != nil {
+ return nil, err
+ }
+
+ tryVT := raw | windows.ENABLE_VIRTUAL_TERMINAL_INPUT
+
+ if err := windows.SetConsoleMode(handle, tryVT); err != nil {
+ if err := windows.SetConsoleMode(handle, raw); err != nil {
+ return nil, err
+ }
+ }
+
+ return state, nil
+}
+
+func notifyWinChange(ctx context.Context, winChange chan os.Signal, stdin *os.File, stdout *os.File) {
+ // Simulate WINCH with polling
+ go func() {
+ var lastW int
+ var lastH int
+
+ d := time.Millisecond * 250
+ timer := time.NewTimer(d)
+ defer timer.Stop()
+ for ; ; timer.Reset(d) {
+ select {
+ case <-ctx.Done():
+ return
+ case <-timer.C:
+ break
+ }
+
+ w, h, err := terminal.GetSize(int(stdout.Fd()))
+ if err != nil {
+ continue
+ }
+ if w != lastW || h != lastH {
+ winChange <- sig.SIGWINCH
+ lastW, lastH = w, h
+ }
+ }
+ }()
+
+}
+
+func getTermSize(stdin *os.File, stdout *os.File) (width, height int, err error) {
+ return terminal.GetSize(int(stdout.Fd()))
+}
diff --git a/pkg/bindings/containers/types.go b/pkg/bindings/containers/types.go
index 66b90af9b..c87f82bf4 100644
--- a/pkg/bindings/containers/types.go
+++ b/pkg/bindings/containers/types.go
@@ -64,14 +64,21 @@ type RestoreOptions struct {
IgnoreVolumes *bool
IgnoreStaticIP *bool
IgnoreStaticMAC *bool
- ImportAchive *string
- Keep *bool
- Name *string
- TCPEstablished *bool
- Pod *string
- PrintStats *bool
- PublishPorts []string
- FileLocks *bool
+ // ImportAchive is the path to an archive which contains the checkpoint data.
+ //
+ // Deprecated: Use ImportArchive instead. This field name is a typo and
+ // will be removed in a future major release.
+ ImportAchive *string
+ // ImportArchive is the path to an archive which contains the checkpoint data.
+ // ImportArchive is preferred over ImportAchive when both are set.
+ ImportArchive *string
+ Keep *bool
+ Name *string
+ TCPEstablished *bool
+ Pod *string
+ PrintStats *bool
+ PublishPorts []string
+ FileLocks *bool
}
//go:generate go run ../generator/generator.go CreateOptions
diff --git a/pkg/bindings/containers/types_restore_options.go b/pkg/bindings/containers/types_restore_options.go
index d2778396a..b1b14a704 100644
--- a/pkg/bindings/containers/types_restore_options.go
+++ b/pkg/bindings/containers/types_restore_options.go
@@ -92,6 +92,21 @@ func (o *RestoreOptions) GetImportAchive() string {
return *o.ImportAchive
}
+// WithImportArchive set field ImportArchive to given value
+func (o *RestoreOptions) WithImportArchive(value string) *RestoreOptions {
+ o.ImportArchive = &value
+ return o
+}
+
+// GetImportArchive returns value of field ImportArchive
+func (o *RestoreOptions) GetImportArchive() string {
+ if o.ImportArchive == nil {
+ var z string
+ return z
+ }
+ return *o.ImportArchive
+}
+
// WithKeep set field Keep to given value
func (o *RestoreOptions) WithKeep(value bool) *RestoreOptions {
o.Keep = &value
diff --git a/pkg/bindings/generator/generator.go b/pkg/bindings/generator/generator.go
index a224013ea..e69973be1 100644
--- a/pkg/bindings/generator/generator.go
+++ b/pkg/bindings/generator/generator.go
@@ -1,3 +1,4 @@
+//go:build ignore
// +build ignore
package main
diff --git a/pkg/bindings/images/build_unix.go b/pkg/bindings/images/build_unix.go
index 0afb1deb6..67a5e2998 100644
--- a/pkg/bindings/images/build_unix.go
+++ b/pkg/bindings/images/build_unix.go
@@ -1,3 +1,4 @@
+//go:build !windows
// +build !windows
package images
diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go
index a44a3527f..75cb38a0a 100644
--- a/pkg/bindings/images/types.go
+++ b/pkg/bindings/images/types.go
@@ -11,6 +11,8 @@ type RemoveOptions struct {
All *bool
// Forces removes all containers based on the image
Force *bool
+ // Ignore if a specified image does not exist and do not throw an error.
+ Ignore *bool
}
//go:generate go run ../generator/generator.go DiffOptions
@@ -101,6 +103,12 @@ type ImportOptions struct {
Reference *string
// Url to option image to import. Cannot be used with the reader
URL *string
+ // OS for the imported image
+ OS *string
+ // Architecture for the imported image
+ Architecture *string
+ // Variant for the imported image
+ Variant *string
}
//go:generate go run ../generator/generator.go PushOptions
diff --git a/pkg/bindings/images/types_import_options.go b/pkg/bindings/images/types_import_options.go
index ea66fa312..f958fe8b4 100644
--- a/pkg/bindings/images/types_import_options.go
+++ b/pkg/bindings/images/types_import_options.go
@@ -76,3 +76,48 @@ func (o *ImportOptions) GetURL() string {
}
return *o.URL
}
+
+// WithOS set field OS to given value
+func (o *ImportOptions) WithOS(value string) *ImportOptions {
+ o.OS = &value
+ return o
+}
+
+// GetOS returns value of field OS
+func (o *ImportOptions) GetOS() string {
+ if o.OS == nil {
+ var z string
+ return z
+ }
+ return *o.OS
+}
+
+// WithArchitecture set field Architecture to given value
+func (o *ImportOptions) WithArchitecture(value string) *ImportOptions {
+ o.Architecture = &value
+ return o
+}
+
+// GetArchitecture returns value of field Architecture
+func (o *ImportOptions) GetArchitecture() string {
+ if o.Architecture == nil {
+ var z string
+ return z
+ }
+ return *o.Architecture
+}
+
+// WithVariant set field Variant to given value
+func (o *ImportOptions) WithVariant(value string) *ImportOptions {
+ o.Variant = &value
+ return o
+}
+
+// GetVariant returns value of field Variant
+func (o *ImportOptions) GetVariant() string {
+ if o.Variant == nil {
+ var z string
+ return z
+ }
+ return *o.Variant
+}
diff --git a/pkg/bindings/images/types_remove_options.go b/pkg/bindings/images/types_remove_options.go
index 1fbe5f4ea..613a33183 100644
--- a/pkg/bindings/images/types_remove_options.go
+++ b/pkg/bindings/images/types_remove_options.go
@@ -46,3 +46,18 @@ func (o *RemoveOptions) GetForce() bool {
}
return *o.Force
}
+
+// WithIgnore set field Ignore to given value
+func (o *RemoveOptions) WithIgnore(value bool) *RemoveOptions {
+ o.Ignore = &value
+ return o
+}
+
+// GetIgnore returns value of field Ignore
+func (o *RemoveOptions) GetIgnore() bool {
+ if o.Ignore == nil {
+ var z bool
+ return z
+ }
+ return *o.Ignore
+}
diff --git a/pkg/bindings/play/play.go b/pkg/bindings/play/play.go
index d4018b6b3..8058a8514 100644
--- a/pkg/bindings/play/play.go
+++ b/pkg/bindings/play/play.go
@@ -2,6 +2,7 @@ package play
import (
"context"
+ "io"
"net/http"
"os"
"strconv"
@@ -14,20 +15,25 @@ import (
)
func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.PlayKubeReport, error) {
+ f, err := os.Open(path)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ return KubeWithBody(ctx, f, options)
+}
+
+func KubeWithBody(ctx context.Context, body io.Reader, options *KubeOptions) (*entities.PlayKubeReport, error) {
var report entities.PlayKubeReport
if options == nil {
options = new(KubeOptions)
}
- conn, err := bindings.GetClient(ctx)
- if err != nil {
- return nil, err
- }
- f, err := os.Open(path)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- defer f.Close()
params, err := options.ToParams()
if err != nil {
@@ -46,7 +52,7 @@ func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.Pla
return nil, err
}
- response, err := conn.DoRequest(ctx, f, http.MethodPost, "/play/kube", params, header)
+ response, err := conn.DoRequest(ctx, body, http.MethodPost, "/play/kube", params, header)
if err != nil {
return nil, err
}
@@ -60,12 +66,6 @@ func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.Pla
}
func KubeDown(ctx context.Context, path string) (*entities.PlayKubeReport, error) {
- var report entities.PlayKubeReport
- conn, err := bindings.GetClient(ctx)
- if err != nil {
- return nil, err
- }
-
f, err := os.Open(path)
if err != nil {
return nil, err
@@ -75,7 +75,18 @@ func KubeDown(ctx context.Context, path string) (*entities.PlayKubeReport, error
logrus.Warn(err)
}
}()
- response, err := conn.DoRequest(ctx, f, http.MethodDelete, "/play/kube", nil, nil)
+
+ return KubeDownWithBody(ctx, f)
+}
+
+func KubeDownWithBody(ctx context.Context, body io.Reader) (*entities.PlayKubeReport, error) {
+ var report entities.PlayKubeReport
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := conn.DoRequest(ctx, body, http.MethodDelete, "/play/kube", nil, nil)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/play/types.go b/pkg/bindings/play/types.go
index ca639e46b..dbff4304b 100644
--- a/pkg/bindings/play/types.go
+++ b/pkg/bindings/play/types.go
@@ -7,6 +7,8 @@ import (
//go:generate go run ../generator/generator.go KubeOptions
// KubeOptions are optional options for replaying kube YAML files
type KubeOptions struct {
+ // Annotations - Annotations to add to Pods
+ Annotations map[string]string
// Authfile - path to an authentication file.
Authfile *string
// CertDir - to a directory containing TLS certifications and keys.
diff --git a/pkg/bindings/play/types_kube_options.go b/pkg/bindings/play/types_kube_options.go
index 83a6f1566..d7a452ea2 100644
--- a/pkg/bindings/play/types_kube_options.go
+++ b/pkg/bindings/play/types_kube_options.go
@@ -18,6 +18,21 @@ func (o *KubeOptions) ToParams() (url.Values, error) {
return util.ToParams(o)
}
+// WithAnnotations set field Annotations to given value
+func (o *KubeOptions) WithAnnotations(value map[string]string) *KubeOptions {
+ o.Annotations = value
+ return o
+}
+
+// GetAnnotations returns value of field Annotations
+func (o *KubeOptions) GetAnnotations() map[string]string {
+ if o.Annotations == nil {
+ var z map[string]string
+ return z
+ }
+ return o.Annotations
+}
+
// WithAuthfile set field Authfile to given value
func (o *KubeOptions) WithAuthfile(value string) *KubeOptions {
o.Authfile = &value
diff --git a/pkg/bindings/test/attach_test.go b/pkg/bindings/test/attach_test.go
index 670566882..dcebe0809 100644
--- a/pkg/bindings/test/attach_test.go
+++ b/pkg/bindings/test/attach_test.go
@@ -44,7 +44,8 @@ var _ = Describe("Podman containers attach", func() {
timeout := uint(5)
err := containers.Stop(bt.conn, id, new(containers.StopOptions).WithTimeout(timeout))
if err != nil {
- GinkgoWriter.Write([]byte(err.Error()))
+ _, writeErr := GinkgoWriter.Write([]byte(err.Error()))
+ Expect(writeErr).ShouldNot(HaveOccurred())
}
}()
diff --git a/pkg/bindings/test/auth_test.go b/pkg/bindings/test/auth_test.go
index b421f0797..c4c4b16d8 100644
--- a/pkg/bindings/test/auth_test.go
+++ b/pkg/bindings/test/auth_test.go
@@ -40,7 +40,8 @@ var _ = Describe("Podman images", func() {
AfterEach(func() {
s.Kill()
bt.cleanup()
- registry.Stop()
+ err := registry.Stop()
+ Expect(err).To(BeNil())
})
// Test using credentials.
diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go
index f51e5f404..f2602967b 100644
--- a/pkg/bindings/test/common_test.go
+++ b/pkg/bindings/test/common_test.go
@@ -211,7 +211,7 @@ func (b *bindingTest) RunTopContainer(containerName *string, podName *string) (s
}
ctr, err := containers.CreateWithSpec(b.conn, s, nil)
if err != nil {
- return "", nil
+ return "", err
}
err = containers.Start(b.conn, ctr.ID, nil)
if err != nil {
diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go
index 9411d8a5f..bf627fdba 100644
--- a/pkg/bindings/test/containers_test.go
+++ b/pkg/bindings/test/containers_test.go
@@ -322,7 +322,8 @@ var _ = Describe("Podman containers ", func() {
// a container that has no healthcheck should be a 409
var name = "top"
- bt.RunTopContainer(&name, nil)
+ _, err = bt.RunTopContainer(&name, nil)
+ Expect(err).To(BeNil())
_, err = containers.RunHealthCheck(bt.conn, name, nil)
Expect(err).ToNot(BeNil())
code, _ = bindings.CheckResponseCode(err)