mirror of
https://github.com/containers/podman.git
synced 2026-02-19 15:39:50 -05:00
Implement TLS API Support
* Added flags to point to TLS PEM files to use for exposing and connecting to an encrypted remote API socket with server and client authentication. * Added TLS fields for system connection ls templates. * Added special "tls" format for system connection ls to list TLS fields in human-readable table format. * Updated remote integration and system tests to allow specifying a "transport" to run the full suite against a unix, tcp, tls, or mtls system service. * Added system tests to verify basic operation of unix, tcp, tls, and mtls services, clients, and connections. Signed-off-by: Andrew Melnick <meln5674.5674@gmail.com>
This commit is contained in:
49
Makefile
49
Makefile
@@ -150,12 +150,17 @@ GINKGO ?= ./bin/ginkgo
|
||||
GINKGO_FLAKE_ATTEMPTS ?= 0
|
||||
GINKGO_NO_COLOR ?= y
|
||||
|
||||
# The type of transport to use for testing remote service.
|
||||
# Must be one of unix, tcp, tls, mtls
|
||||
export REMOTESYSTEM_TRANSPORT ?= unix
|
||||
export REMOTEINTEGRATION_TRANSPORT ?= unix
|
||||
|
||||
# Conditional required to produce empty-output if binary not built yet.
|
||||
RELEASE_VERSION = $(shell if test -x test/version/version; then test/version/version; fi)
|
||||
RELEASE_NUMBER = $(shell echo "$(call err_if_empty,RELEASE_VERSION)" | sed -e 's/^v\(.*\)/\1/')
|
||||
|
||||
# If non-empty, logs all output from server during remote system testing
|
||||
PODMAN_SERVER_LOG ?=
|
||||
# Logs all output from server during remote system testing to this file
|
||||
PODMAN_SERVER_LOG ?= /dev/null
|
||||
|
||||
# Ensure GOBIN is not set so the default (`go env GOPATH`/bin) is used.
|
||||
override undefine GOBIN
|
||||
@@ -680,6 +685,7 @@ ginkgo-run: .install.ginkgo
|
||||
ginkgo:
|
||||
$(MAKE) ginkgo-run TAGS="$(BUILDTAGS)"
|
||||
|
||||
|
||||
.PHONY: ginkgo-remote
|
||||
ginkgo-remote:
|
||||
$(MAKE) ginkgo-run TAGS="$(REMOTETAGS) remote_testing"
|
||||
@@ -709,44 +715,15 @@ localsystem:
|
||||
PODMAN=$(CURDIR)/bin/podman QUADLET=$(CURDIR)/bin/quadlet bats -T --filter-tags '!ci:parallel' test/system/
|
||||
PODMAN=$(CURDIR)/bin/podman QUADLET=$(CURDIR)/bin/quadlet bats -T --filter-tags ci:parallel -j $$(nproc) test/system/
|
||||
|
||||
|
||||
.PHONY: remotesystem
|
||||
remotesystem:
|
||||
# Wipe existing config, database, and cache: start with clean slate.
|
||||
$(RM) -rf ${HOME}/.local/share/containers ${HOME}/.config/containers
|
||||
# . Make sure there's no active podman server - if there is,
|
||||
# it's not us, and we have no way to know what it is.
|
||||
# . Start server. Wait to make sure it comes up.
|
||||
# . Run tests, pretty much the same as localsystem.
|
||||
# . Stop server.
|
||||
rc=0;\
|
||||
if timeout -v 1 true; then \
|
||||
if ./bin/podman-remote info; then \
|
||||
echo "Error: podman system service (not ours) is already running" >&2;\
|
||||
exit 1;\
|
||||
fi;\
|
||||
./bin/podman system service --timeout=0 > $(if $(PODMAN_SERVER_LOG),$(PODMAN_SERVER_LOG),/dev/null) 2>&1 & \
|
||||
retry=5;\
|
||||
while [ $$retry -ge 0 ]; do\
|
||||
echo Waiting for server...;\
|
||||
sleep 1;\
|
||||
./bin/podman-remote info >/dev/null 2>&1 && break;\
|
||||
retry=$$(expr $$retry - 1);\
|
||||
done;\
|
||||
if [ $$retry -lt 0 ]; then\
|
||||
echo "Error: ./bin/podman system service did not come up" >&2;\
|
||||
exit 1;\
|
||||
fi;\
|
||||
env PODMAN="$(CURDIR)/bin/podman-remote" bats -T --filter-tags '!ci:parallel' test/system/ ;\
|
||||
rc=$$?; \
|
||||
if [ $$rc -eq 0 ]; then \
|
||||
env PODMAN="$(CURDIR)/bin/podman-remote" bats -T --filter-tags ci:parallel -j $$(nproc) test/system/ ;\
|
||||
rc=$$?;\
|
||||
fi; \
|
||||
kill %1;\
|
||||
else \
|
||||
echo "Skipping $@: 'timeout -v' unavailable'";\
|
||||
fi;\
|
||||
exit $$rc
|
||||
PODMAN=$(CURDIR)/bin/podman-remote QUADLET=$(CURDIR)/bin/quadlet \
|
||||
bats -T --filter-tags '!ci:parallel' test/system/
|
||||
PODMAN=$(CURDIR)/bin/podman-remote QUADLET=$(CURDIR)/bin/quadlet \
|
||||
bats -T --filter-tags ci:parallel -j $$(nproc) test/system/
|
||||
|
||||
.PHONY: localapiv2-bash
|
||||
localapiv2-bash:
|
||||
|
||||
@@ -167,6 +167,9 @@ func readRemoteCliFlags(cmd *cobra.Command, podmanConfig *entities.PodmanConfig)
|
||||
}
|
||||
podmanConfig.URI = con.URI
|
||||
podmanConfig.Identity = con.Identity
|
||||
podmanConfig.TLSCertFile = con.TLSCert
|
||||
podmanConfig.TLSKeyFile = con.TLSKey
|
||||
podmanConfig.TLSCAFile = con.TLSCA
|
||||
podmanConfig.MachineMode = con.IsMachine
|
||||
case url.Changed:
|
||||
podmanConfig.URI = url.Value.String()
|
||||
@@ -179,6 +182,9 @@ func readRemoteCliFlags(cmd *cobra.Command, podmanConfig *entities.PodmanConfig)
|
||||
}
|
||||
podmanConfig.URI = con.URI
|
||||
podmanConfig.Identity = con.Identity
|
||||
podmanConfig.TLSCertFile = con.TLSCert
|
||||
podmanConfig.TLSKeyFile = con.TLSKey
|
||||
podmanConfig.TLSCAFile = con.TLSCA
|
||||
podmanConfig.MachineMode = con.IsMachine
|
||||
}
|
||||
case host.Changed:
|
||||
@@ -213,6 +219,9 @@ func setupRemoteConnection(podmanConfig *entities.PodmanConfig) string {
|
||||
}
|
||||
podmanConfig.URI = con.URI
|
||||
podmanConfig.Identity = con.Identity
|
||||
podmanConfig.TLSCertFile = con.TLSCert
|
||||
podmanConfig.TLSKeyFile = con.TLSKey
|
||||
podmanConfig.TLSCAFile = con.TLSCA
|
||||
podmanConfig.MachineMode = con.IsMachine
|
||||
return con.Name
|
||||
case hostEnv != "":
|
||||
@@ -225,6 +234,9 @@ func setupRemoteConnection(podmanConfig *entities.PodmanConfig) string {
|
||||
if err == nil {
|
||||
podmanConfig.URI = con.URI
|
||||
podmanConfig.Identity = con.Identity
|
||||
podmanConfig.TLSCertFile = con.TLSCert
|
||||
podmanConfig.TLSKeyFile = con.TLSKey
|
||||
podmanConfig.TLSCAFile = con.TLSCA
|
||||
podmanConfig.MachineMode = con.IsMachine
|
||||
return con.Name
|
||||
}
|
||||
@@ -521,6 +533,18 @@ func rootFlags(cmd *cobra.Command, podmanConfig *entities.PodmanConfig) {
|
||||
lFlags.StringVar(&podmanConfig.Identity, identityFlagName, podmanConfig.Identity, "path to SSH identity file, (CONTAINER_SSHKEY)")
|
||||
_ = cmd.RegisterFlagCompletionFunc(identityFlagName, completion.AutocompleteDefault)
|
||||
|
||||
tlsCertFileFlagName := "tls-cert"
|
||||
lFlags.StringVar(&podmanConfig.TLSCertFile, tlsCertFileFlagName, podmanConfig.TLSCertFile, "path to TLS client certificate PEM file for remote.")
|
||||
_ = cmd.RegisterFlagCompletionFunc(tlsCertFileFlagName, completion.AutocompleteDefault)
|
||||
|
||||
tlsKeyFileFlagName := "tls-key"
|
||||
lFlags.StringVar(&podmanConfig.TLSKeyFile, tlsKeyFileFlagName, podmanConfig.TLSKeyFile, "path to TLS client certificate private key PEM file for remote.")
|
||||
_ = cmd.RegisterFlagCompletionFunc(tlsKeyFileFlagName, completion.AutocompleteDefault)
|
||||
|
||||
tlsCAFileFlagName := "tls-ca"
|
||||
lFlags.StringVar(&podmanConfig.TLSCAFile, tlsCAFileFlagName, podmanConfig.TLSCAFile, "path to TLS certificate Authority PEM file for remote.")
|
||||
_ = cmd.RegisterFlagCompletionFunc(tlsCAFileFlagName, completion.AutocompleteDefault)
|
||||
|
||||
// Flags that control or influence any kind of output.
|
||||
outFlagName := "out"
|
||||
lFlags.StringVar(&useStdout, outFlagName, "", "Send output (stdout) from podman to a file")
|
||||
|
||||
@@ -27,7 +27,7 @@ var (
|
||||
"destination" is one of the form:
|
||||
[user@]hostname (will default to ssh)
|
||||
ssh://[user@]hostname[:port][/path] (will obtain socket path from service, if not given.)
|
||||
tcp://hostname:port (not secured)
|
||||
tcp://hostname:port (not secured without TLS enabled)
|
||||
unix://path (absolute path required)
|
||||
`,
|
||||
RunE: add,
|
||||
@@ -36,6 +36,7 @@ var (
|
||||
podman system connection add --identity ~/.ssh/dev_rsa testing ssh://root@server.fubar.com:2222
|
||||
podman system connection add --identity ~/.ssh/dev_rsa --port 22 production root@server.fubar.com
|
||||
podman system connection add debug tcp://localhost:8080
|
||||
podman system connection add production-tls --tls-ca=ca.crt --tls-cert=tls.crt --tls-key=tls.key tcp://localhost:8080
|
||||
`,
|
||||
}
|
||||
|
||||
@@ -51,11 +52,14 @@ var (
|
||||
dockerPath string
|
||||
|
||||
cOpts = struct {
|
||||
Identity string
|
||||
Port int
|
||||
UDSPath string
|
||||
Default bool
|
||||
Farm string
|
||||
Identity string
|
||||
Port int
|
||||
UDSPath string
|
||||
Default bool
|
||||
Farm string
|
||||
TLSCertFile string
|
||||
TLSKeyFile string
|
||||
TLSCAFile string
|
||||
}{}
|
||||
)
|
||||
|
||||
@@ -74,6 +78,18 @@ func init() {
|
||||
flags.StringVar(&cOpts.Identity, identityFlagName, "", "path to SSH identity file")
|
||||
_ = addCmd.RegisterFlagCompletionFunc(identityFlagName, completion.AutocompleteDefault)
|
||||
|
||||
tlsCertFileFlagName := "tls-cert"
|
||||
flags.StringVar(&cOpts.TLSCertFile, tlsCertFileFlagName, "", "path to TLS client certificate PEM file")
|
||||
_ = addCmd.RegisterFlagCompletionFunc(tlsCertFileFlagName, completion.AutocompleteDefault)
|
||||
|
||||
tlsKeyFileFlagName := "tls-key"
|
||||
flags.StringVar(&cOpts.TLSKeyFile, tlsKeyFileFlagName, "", "path to TLS client certificate private key PEM file")
|
||||
_ = addCmd.RegisterFlagCompletionFunc(tlsKeyFileFlagName, completion.AutocompleteDefault)
|
||||
|
||||
tlsCAFileFlagName := "tls-ca"
|
||||
flags.StringVar(&cOpts.TLSCAFile, tlsCAFileFlagName, "", "path to TLS certificate Authority PEM file")
|
||||
_ = addCmd.RegisterFlagCompletionFunc(tlsCAFileFlagName, completion.AutocompleteDefault)
|
||||
|
||||
socketPathFlagName := "socket-path"
|
||||
flags.StringVar(&cOpts.UDSPath, socketPathFlagName, "", "path to podman socket on remote host. (default '/run/podman/podman.sock' or '/run/user/{uid}/podman/podman.sock)")
|
||||
_ = addCmd.RegisterFlagCompletionFunc(socketPathFlagName, completion.AutocompleteDefault)
|
||||
@@ -139,6 +155,17 @@ func add(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("invalid ssh mode")
|
||||
}
|
||||
|
||||
if uri.Scheme != "tcp" {
|
||||
if cmd.Flags().Changed("tls-cert") {
|
||||
return fmt.Errorf("--tls-cert option not supported for %s scheme", uri.Scheme)
|
||||
}
|
||||
if cmd.Flags().Changed("tls-key") {
|
||||
return fmt.Errorf("--tls-key option not supported for %s scheme", uri.Scheme)
|
||||
}
|
||||
if cmd.Flags().Changed("tls-ca") {
|
||||
return fmt.Errorf("--tls-ca option not supported for %s scheme", uri.Scheme)
|
||||
}
|
||||
}
|
||||
switch uri.Scheme {
|
||||
case "ssh":
|
||||
return ssh.Create(entities, sshMode)
|
||||
@@ -146,7 +173,6 @@ func add(cmd *cobra.Command, args []string) error {
|
||||
if cmd.Flags().Changed("identity") {
|
||||
return errors.New("--identity option not supported for unix scheme")
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("socket-path") {
|
||||
uri.Path = cmd.Flag("socket-path").Value.String()
|
||||
}
|
||||
@@ -169,6 +195,9 @@ func add(cmd *cobra.Command, args []string) error {
|
||||
if cmd.Flags().Changed("identity") {
|
||||
return errors.New("--identity option not supported for tcp scheme")
|
||||
}
|
||||
if cmd.Flags().Changed("tls-cert") != cmd.Flags().Changed("tls-key") {
|
||||
return errors.New("--tls-cert and --tls-key options must be both provided if one is provided")
|
||||
}
|
||||
if uri.Port() == "" {
|
||||
return errors.New("tcp scheme requires a port either via --port or in destination URL")
|
||||
}
|
||||
@@ -179,6 +208,9 @@ func add(cmd *cobra.Command, args []string) error {
|
||||
dst := config.Destination{
|
||||
URI: uri.String(),
|
||||
Identity: cOpts.Identity,
|
||||
TLSCert: cOpts.TLSCertFile,
|
||||
TLSKey: cOpts.TLSKeyFile,
|
||||
TLSCA: cOpts.TLSCAFile,
|
||||
}
|
||||
|
||||
connection := args[0]
|
||||
|
||||
@@ -24,8 +24,14 @@ var (
|
||||
Short: "List destination for the Podman service(s)",
|
||||
Long: `List destination information for the Podman service(s) in podman configuration`,
|
||||
Example: `podman system connection list
|
||||
# Format as table without TLS info
|
||||
podman system connection ls
|
||||
podman system connection ls --format=json`,
|
||||
# Format as table with TLS info
|
||||
podman system connection ls --format=tls
|
||||
# Format as JSON
|
||||
podman system connection ls --format=json
|
||||
# Format as custom go template
|
||||
podman system connection ls --format='{{range .}}{{.Name}}{{ "\n" }}{{ end }}'`,
|
||||
ValidArgsFunction: completion.AutocompleteNone,
|
||||
RunE: list,
|
||||
TraverseChildren: false,
|
||||
@@ -114,12 +120,17 @@ func inspect(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if format != "" {
|
||||
rpt, err = rpt.Parse(report.OriginUser, format)
|
||||
} else {
|
||||
switch format {
|
||||
case "tls":
|
||||
rpt, err = rpt.Parse(report.OriginPodman,
|
||||
"{{range .}}{{.Name}}\t{{.URI}}\t{{.Identity}}\t{{.TLSCA}}\t{{.TLSCert}}\t{{.TLSKey}}\t{{.Default}}\t{{.ReadWrite}}\n{{end -}}")
|
||||
case "":
|
||||
rpt, err = rpt.Parse(report.OriginPodman,
|
||||
"{{range .}}{{.Name}}\t{{.URI}}\t{{.Identity}}\t{{.Default}}\t{{.ReadWrite}}\n{{end -}}")
|
||||
default:
|
||||
rpt, err = rpt.Parse(report.OriginUser, format)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -128,6 +139,9 @@ func inspect(cmd *cobra.Command, args []string) error {
|
||||
err = rpt.Execute([]map[string]string{{
|
||||
"Default": "Default",
|
||||
"Identity": "Identity",
|
||||
"TLSCA": "TLSCA",
|
||||
"TLSCert": "TLSCert",
|
||||
"TLSKey": "TLSKey",
|
||||
"Name": "Name",
|
||||
"URI": "URI",
|
||||
"ReadWrite": "ReadWrite",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -36,13 +37,19 @@ Enable a listening service for API access to Podman commands.
|
||||
RunE: service,
|
||||
ValidArgsFunction: common.AutocompleteDefaultOneArg,
|
||||
Example: `podman system service --time=0 unix:///tmp/podman.sock
|
||||
podman system service --time=0 tcp://localhost:8888`,
|
||||
podman system service --time=0 tcp://localhost:8888
|
||||
podman system service --time=0 --tls-cert=tls.crt --tls-key=tls.key tcp://localhost:8888
|
||||
podman system service --time=0 --tls-cert=tls.crt --tls-key=tls.key --tls-client-ca=ca.crt tcp://localhost:8888
|
||||
`,
|
||||
}
|
||||
|
||||
srvArgs = struct {
|
||||
CorsHeaders string
|
||||
PProfAddr string
|
||||
Timeout uint
|
||||
CorsHeaders string
|
||||
PProfAddr string
|
||||
Timeout uint
|
||||
TLSCertFile string
|
||||
TLSKeyFile string
|
||||
TLSClientCAFile string
|
||||
}{}
|
||||
)
|
||||
|
||||
@@ -67,6 +74,16 @@ func init() {
|
||||
flags.StringVarP(&srvArgs.PProfAddr, "pprof-address", "", "",
|
||||
"Binding network address for pprof profile endpoints, default: do not expose endpoints")
|
||||
_ = flags.MarkHidden("pprof-address")
|
||||
|
||||
flags.StringVarP(&srvArgs.TLSCertFile, "tls-cert", "", "",
|
||||
"PEM file containing TLS serving certificate.")
|
||||
_ = srvCmd.RegisterFlagCompletionFunc("tls-cert", completion.AutocompleteDefault)
|
||||
flags.StringVarP(&srvArgs.TLSKeyFile, "tls-key", "", "",
|
||||
"PEM file containing TLS serving certificate private key")
|
||||
_ = srvCmd.RegisterFlagCompletionFunc("tls-key", completion.AutocompleteDefault)
|
||||
flags.StringVarP(&srvArgs.TLSClientCAFile, "tls-client-ca", "", "",
|
||||
"Only trust client connections with certificates signed by this CA PEM file")
|
||||
_ = srvCmd.RegisterFlagCompletionFunc("tls-client-ca", completion.AutocompleteDefault)
|
||||
}
|
||||
|
||||
func aliasTimeoutFlag(_ *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
@@ -99,11 +116,21 @@ func service(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
if len(srvArgs.TLSCertFile) != 0 && len(srvArgs.TLSKeyFile) == 0 {
|
||||
return fmt.Errorf("--tls-cert provided without --tls-key")
|
||||
}
|
||||
if len(srvArgs.TLSKeyFile) != 0 && len(srvArgs.TLSCertFile) == 0 {
|
||||
return fmt.Errorf("--tls-key provided without --tls-cert")
|
||||
}
|
||||
|
||||
return restService(cmd.Flags(), registry.PodmanConfig(), entities.ServiceOptions{
|
||||
CorsHeaders: srvArgs.CorsHeaders,
|
||||
PProfAddr: srvArgs.PProfAddr,
|
||||
Timeout: time.Duration(srvArgs.Timeout) * time.Second,
|
||||
URI: apiURI,
|
||||
CorsHeaders: srvArgs.CorsHeaders,
|
||||
PProfAddr: srvArgs.PProfAddr,
|
||||
Timeout: time.Duration(srvArgs.Timeout) * time.Second,
|
||||
URI: apiURI,
|
||||
TLSCertFile: srvArgs.TLSCertFile,
|
||||
TLSKeyFile: srvArgs.TLSKeyFile,
|
||||
TLSClientCAFile: srvArgs.TLSClientCAFile,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -76,11 +76,13 @@ func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities
|
||||
}
|
||||
}
|
||||
case "tcp":
|
||||
// We want to check if the user is requesting a TCP address.
|
||||
// We want to check if the user is requesting a TCP address if TLS is not active.
|
||||
// If so, warn that this is insecure.
|
||||
// Ignore errors here, the actual backend code will handle them
|
||||
// better than we can here.
|
||||
logrus.Warnf("Using the Podman API service with TCP sockets is not recommended, please see `podman system service` manpage for details")
|
||||
if opts.TLSKeyFile == "" || opts.TLSCertFile == "" {
|
||||
logrus.Warnf("Using the Podman API service with TCP sockets without TLS is not recommended, please see `podman system service` manpage for details")
|
||||
}
|
||||
|
||||
host := uri.Host
|
||||
if host == "" {
|
||||
|
||||
@@ -35,6 +35,18 @@ Port for ssh destination. The default value is `22`.
|
||||
|
||||
Path to the Podman service unix domain socket on the ssh destination host
|
||||
|
||||
#### **--tls-ca**=*path*
|
||||
|
||||
Path to a PEM file containing the certificate authority bundle to verify the server's certificate against.
|
||||
|
||||
#### **--tls-cert**=*path*
|
||||
|
||||
Path to a PEM file containing the TLS client certificate to present to the server. `--tls-key` must also be provided.
|
||||
|
||||
#### **--tls-key**=*path*
|
||||
|
||||
Path to a PEM file containing the private key matching `--tls-cert`. `--tls-cert` must also be provided.
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
Add a named system connection:
|
||||
@@ -55,6 +67,7 @@ $ podman system connection add testing unix:///run/podman/podman.sock
|
||||
Add a named system connection to local tcp socket:
|
||||
```
|
||||
$ podman system connection add debug tcp://localhost:8080
|
||||
|
||||
```
|
||||
Add a connection with a custom port:
|
||||
```
|
||||
@@ -70,6 +83,11 @@ Add a connection and make it the default:
|
||||
```
|
||||
$ podman system connection add --default production root@prod.example.com
|
||||
```
|
||||
|
||||
Add a named system connection to remote tcp socket secured via TLS:
|
||||
```
|
||||
$ podman system connection add secure-debug --tls-cert=tls.crt --tls-key=tls.key --tls-ca=ca.crt tcp://podman.example.com:8443
|
||||
```
|
||||
## SEE ALSO
|
||||
**[podman(1)](podman.1.md)**, **[podman-system(1)](podman-system.1.md)**, **[podman-system-connection(1)](podman-system-connection.1.md)**
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ Valid placeholders for the Go template listed below:
|
||||
| .Identity | Path to file containing SSH identity |
|
||||
| .Name | Connection Name/Identifier |
|
||||
| .ReadWrite | Indicates if this connection can be modified using the system connection commands |
|
||||
| .TLSCA | Path to a PEM file containing the certificate authority bundle to verify the server's certificate against. |
|
||||
| .TLSCert | Path to a PEM file containing the certificate authority bundle to verify the server's certificate against. |
|
||||
| .TLSKey | Path to a PEM file containing the private key matching `.TLSCA` |
|
||||
| .URI | URI to podman service. Valid schemes are ssh://[user@]*host*[:port]*Unix domain socket*[?secure=True], unix://*Unix domain socket*, and tcp://localhost[:*port*] |
|
||||
|
||||
#### **--quiet**, **-q**
|
||||
|
||||
@@ -70,10 +70,11 @@ To access the API service inside a container:
|
||||
|
||||
Please note that the API grants full access to all Podman functionality, and thus allows arbitrary code execution as the user running the API, with no ability to limit or audit this access.
|
||||
The API's security model is built upon access via a Unix socket with access restricted via standard file permissions, ensuring that only the user running the service will be able to access it.
|
||||
We *strongly* recommend against making the API socket available via the network (IE, bindings the service to a *tcp* URL).
|
||||
TLS can be used to secure this socket by requiring clients to present a certificate signed by a trusted certificate authority ("CA"), as well as to allow the client to verify the identity of the API.
|
||||
We *strongly* recommend against making the API socket available via the network (IE, bindings the service to a *tcp* URL) without enabling mutual TLS to authenticate the client.
|
||||
Even access via Localhost carries risks - anyone with access to the system will be able to access the API.
|
||||
If remote access is required, we instead recommend forwarding the API socket via SSH, and limiting access on the remote machine to the greatest extent possible.
|
||||
If a *tcp* URL must be used, using the *--cors* option is recommended to improve security.
|
||||
If a *tcp* URL must be used without TLS, using the *--cors* option is recommended to improve security.
|
||||
|
||||
## OPTIONS
|
||||
|
||||
@@ -90,6 +91,19 @@ Print usage statement.
|
||||
The time until the session expires in _seconds_. The default is 5
|
||||
seconds. A value of `0` means no timeout, therefore the session does not expire.
|
||||
|
||||
#### **--tls-cert**=*path*
|
||||
|
||||
Path to a PEM file containing the TLS certificate to present to clients. `--tls-key` must also be provided.
|
||||
|
||||
#### **--tls-client-ca**=*path*
|
||||
|
||||
Path to a PEM file containing the TLS certificate bundle to validate client connections against.
|
||||
Connections that present no certificate or a certificate not signed by one of these certificates will be rejected.
|
||||
|
||||
#### **--tls-key**=*path*
|
||||
|
||||
Path to a PEM file containing the private key matching `--tls-cert`. `--tls-cert` must also be provided.
|
||||
|
||||
The default timeout can be changed via the `service_timeout=VALUE` field in containers.conf.
|
||||
See **[containers.conf(5)](https://github.com/containers/common/blob/main/docs/containers.conf.5.md)** for more information.
|
||||
|
||||
|
||||
@@ -173,6 +173,19 @@ Output logging information to syslog as well as the console (default *false*).
|
||||
|
||||
On remote clients, including Mac and Windows (excluding WSL2) machines, logging is directed to the file $HOME/.config/containers/podman.log.
|
||||
|
||||
#### **--tls-ca**=*path*
|
||||
|
||||
Path to a PEM file containing the certificate authority bundle to verify the server's certificate against.
|
||||
|
||||
#### **--tls-cert**=*path*
|
||||
|
||||
Path to a PEM file containing the TLS client certificate to present to the server. `--tls-key` must also be provided.
|
||||
|
||||
#### **--tls-key**=*path*
|
||||
|
||||
Path to a PEM file containing the private key matching `--tls-cert`. `--tls-cert` must also be provided.
|
||||
|
||||
|
||||
#### **--tmpdir**=*path*
|
||||
|
||||
Path to the tmp directory, for libpod runtime content. Defaults to `$XDG_RUNTIME_DIR/libpod/tmp` as rootless and `/run/libpod/tmp` as rootful.
|
||||
|
||||
18
go.mod
18
go.mod
@@ -3,14 +3,14 @@ module github.com/containers/podman/v5
|
||||
// Warning: if there is a "toolchain" directive anywhere in this file (and most of the
|
||||
// time there shouldn't be), its version must be an exact match to the "go" directive.
|
||||
|
||||
go 1.24.0
|
||||
go 1.24.2
|
||||
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.6.2
|
||||
github.com/blang/semver/v4 v4.0.0
|
||||
github.com/checkpoint-restore/checkpointctl v1.4.0
|
||||
github.com/checkpoint-restore/go-criu/v7 v7.2.0
|
||||
github.com/containernetworking/plugins v1.7.1
|
||||
github.com/containernetworking/plugins v1.8.0
|
||||
github.com/containers/buildah v1.41.1-0.20250829135344-3367a9bc2c9f
|
||||
github.com/containers/conmon v2.0.20+incompatible
|
||||
github.com/containers/gvisor-tap-vsock v0.8.7
|
||||
@@ -65,7 +65,7 @@ require (
|
||||
github.com/vbauerster/mpb/v8 v8.10.2
|
||||
github.com/vishvananda/netlink v1.3.1
|
||||
go.etcd.io/bbolt v1.4.3
|
||||
go.podman.io/common v0.65.0
|
||||
go.podman.io/common v0.65.1-0.20250925174758-4cf0ff781bfc
|
||||
go.podman.io/image/v5 v5.37.0
|
||||
go.podman.io/storage v1.60.0
|
||||
golang.org/x/crypto v0.42.0
|
||||
@@ -119,9 +119,9 @@ require (
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/go-containerregistry v0.20.3 // indirect
|
||||
github.com/google/go-containerregistry v0.20.4-0.20250225234217-098045d5e61f // indirect
|
||||
github.com/google/go-intervals v0.0.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
|
||||
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
|
||||
@@ -145,7 +145,7 @@ require (
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/opencontainers/runc v1.3.0 // indirect
|
||||
github.com/opencontainers/runc v1.3.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/sftp v1.13.9 // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
@@ -156,7 +156,7 @@ require (
|
||||
github.com/seccomp/libseccomp-golang v0.11.1 // indirect
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.9.1 // indirect
|
||||
github.com/segmentio/ksuid v1.0.4 // indirect
|
||||
github.com/sigstore/fulcio v1.6.6 // indirect
|
||||
github.com/sigstore/fulcio v1.7.1 // indirect
|
||||
github.com/sigstore/protobuf-specs v0.4.1 // indirect
|
||||
github.com/sigstore/sigstore v1.9.5 // indirect
|
||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||
@@ -186,8 +186,8 @@ require (
|
||||
golang.org/x/text v0.29.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect
|
||||
google.golang.org/grpc v1.72.2 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
tags.cncf.io/container-device-interface/specs-go v1.0.0 // indirect
|
||||
|
||||
48
go.sum
48
go.sum
@@ -53,8 +53,8 @@ github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++
|
||||
github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
|
||||
github.com/containernetworking/cni v1.3.0 h1:v6EpN8RznAZj9765HhXQrtXgX+ECGebEYEmnuFjskwo=
|
||||
github.com/containernetworking/cni v1.3.0/go.mod h1:Bs8glZjjFfGPHMw6hQu82RUgEPNGEaBb9KS5KtNMnJ4=
|
||||
github.com/containernetworking/plugins v1.7.1 h1:CNAR0jviDj6FS5Vg85NTgKWLDzZPfi/lj+VJfhMDTIs=
|
||||
github.com/containernetworking/plugins v1.7.1/go.mod h1:xuMdjuio+a1oVQsHKjr/mgzuZ24leAsqUYRnzGoXHy0=
|
||||
github.com/containernetworking/plugins v1.8.0 h1:WjGbV/0UQyo8A4qBsAh6GaDAtu1hevxVxsEuqtBqUFk=
|
||||
github.com/containernetworking/plugins v1.8.0/go.mod h1:JG3BxoJifxxHBhG3hFyxyhid7JgRVBu/wtooGEvWf1c=
|
||||
github.com/containers/buildah v1.41.1-0.20250829135344-3367a9bc2c9f h1:t2zdi9mHtJoGmRMXa3i+oD/7xlYHIgoA+/Jtd0Ysf6c=
|
||||
github.com/containers/buildah v1.41.1-0.20250829135344-3367a9bc2c9f/go.mod h1:LtwfkfBed4dUOFTcBG+O+9Vcu5znw/PLYWDJ1mieHic=
|
||||
github.com/containers/common v0.62.2 h1:xO45OOoeq17EZMIDZoSyRqg7GXGcRHa9sXlrr75zH+U=
|
||||
@@ -102,8 +102,8 @@ github.com/disiqueira/gotree/v3 v3.0.2 h1:ik5iuLQQoufZBNPY518dXhiO5056hyNBIK9lWh
|
||||
github.com/disiqueira/gotree/v3 v3.0.2/go.mod h1:ZuyjE4+mUQZlbpkI24AmruZKhg3VHEgPLDY8Qk+uUu8=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/cli v28.3.3+incompatible h1:fp9ZHAr1WWPGdIWBM1b3zLtgCF+83gRdVMTJsUeiyAo=
|
||||
github.com/docker/cli v28.3.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v28.4.0+incompatible h1:RBcf3Kjw2pMtwui5V0DIMdyeab8glEw5QY0UUU4C9kY=
|
||||
github.com/docker/cli v28.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v28.4.0+incompatible h1:KVC7bz5zJY/4AZe/78BIvCnPsLaC9T/zh72xnlrTTOk=
|
||||
@@ -156,15 +156,15 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI=
|
||||
github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI=
|
||||
github.com/google/go-containerregistry v0.20.4-0.20250225234217-098045d5e61f h1:q+kbH7LI4wK3gNCxyvy2rFldJqAAB+Gch79/xj9/+GU=
|
||||
github.com/google/go-containerregistry v0.20.4-0.20250225234217-098045d5e61f/go.mod h1:UnXV0UkKqoHbzwn49vfozmwMcLMS8XLLsVKVuhv3cGc=
|
||||
github.com/google/go-intervals v0.0.2 h1:FGrVEiUnTRKR8yE04qzXYaJMtnIYqobR5QbblK3ixcM=
|
||||
github.com/google/go-intervals v0.0.2/go.mod h1:MkaR3LNRfeKLPmqgJYs4E66z5InYjmCjbbr4TQlcT6Y=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2 h1:CVuJwN34x4xM2aT4sIKhmeib40NeBPhRihNjQmpJsA4=
|
||||
github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY=
|
||||
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@@ -176,8 +176,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E=
|
||||
github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@@ -292,8 +292,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||
github.com/opencontainers/runc v1.3.0 h1:cvP7xbEvD0QQAs0nZKLzkVog2OPZhI/V2w3WmTmUSXI=
|
||||
github.com/opencontainers/runc v1.3.0/go.mod h1:9wbWt42gV+KRxKRVVugNP6D5+PQciRbenB4fLVsqGPs=
|
||||
github.com/opencontainers/runc v1.3.1 h1:c/yY0oh2wK7tzDuD56REnSxyU8ubh8hoAIOLGLrm4SM=
|
||||
github.com/opencontainers/runc v1.3.1/go.mod h1:9wbWt42gV+KRxKRVVugNP6D5+PQciRbenB4fLVsqGPs=
|
||||
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
|
||||
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20250523060157-0ea5ed0382a2 h1:2xZEHOdeQBV6PW8ZtimN863bIOl7OCW/X10K0cnxKeA=
|
||||
@@ -323,8 +323,8 @@ github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
|
||||
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
||||
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
@@ -345,12 +345,12 @@ github.com/secure-systems-lab/go-securesystemslib v0.9.1 h1:nZZaNz4DiERIQguNy0cL
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.9.1/go.mod h1:np53YzT0zXGMv6x4iEWc9Z59uR+x+ndLwCLqPYpLXVU=
|
||||
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
|
||||
github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/shirou/gopsutil/v4 v4.25.8 h1:NnAsw9lN7587WHxjJA9ryDnqhJpFH6A+wagYWTOH970=
|
||||
github.com/shirou/gopsutil/v4 v4.25.8/go.mod h1:q9QdMmfAOVIw7a+eF86P7ISEU6ka+NLgkUxlopV4RwI=
|
||||
github.com/sigstore/fulcio v1.6.6 h1:XaMYX6TNT+8n7Npe8D94nyZ7/ERjEsNGFC+REdi/wzw=
|
||||
github.com/sigstore/fulcio v1.6.6/go.mod h1:BhQ22lwaebDgIxVBEYOOqLRcN5+xOV+C9bh/GUXRhOk=
|
||||
github.com/sigstore/fulcio v1.7.1 h1:RcoW20Nz49IGeZyu3y9QYhyyV3ZKQ85T+FXPKkvE+aQ=
|
||||
github.com/sigstore/fulcio v1.7.1/go.mod h1:7lYY+hsd8Dt+IvKQRC+KEhWpCZ/GlmNvwIa5JhypMS8=
|
||||
github.com/sigstore/protobuf-specs v0.4.1 h1:5SsMqZbdkcO/DNHudaxuCUEjj6x29tS2Xby1BxGU7Zc=
|
||||
github.com/sigstore/protobuf-specs v0.4.1/go.mod h1:+gXR+38nIa2oEupqDdzg4qSBT0Os+sP7oYv6alWewWc=
|
||||
github.com/sigstore/sigstore v1.9.5 h1:Wm1LT9yF4LhQdEMy5A2JeGRHTrAWGjT3ubE5JUSrGVU=
|
||||
@@ -449,8 +449,8 @@ go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
||||
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
||||
go.podman.io/common v0.65.0 h1:8JNl25U4VpKDkFHSymSPm4te7ZQHJbfAB/l2FqtmYEg=
|
||||
go.podman.io/common v0.65.0/go.mod h1:+lJu8KHeoDQsD9HDdiFaMaOUiqPLQnK406WuLnqM7Z0=
|
||||
go.podman.io/common v0.65.1-0.20250925174758-4cf0ff781bfc h1:vLyukLe6FUCUxGDq9IN9WCpbzqHzMk8gQSuRh/z/pcs=
|
||||
go.podman.io/common v0.65.1-0.20250925174758-4cf0ff781bfc/go.mod h1:DyOdwtkwzYA8lE0TueJnxRju4Lmsrx6ZAC/ATAkYYck=
|
||||
go.podman.io/image/v5 v5.37.0 h1:yzgQybwuWIIeK63hu+mQqna/wOh96XD5cpVc6j8Dg5M=
|
||||
go.podman.io/image/v5 v5.37.0/go.mod h1:+s2Sx5dia/jVeT8tI3r2NAPrARMiDdbEq3QPIQogx3I=
|
||||
go.podman.io/storage v1.60.0 h1:bWNSrR58nxg39VNFDSx3m0AswbvyzPGOo5XsUfomTao=
|
||||
@@ -578,10 +578,10 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e h1:UdXH7Kzbj+Vzastr5nVfccbmFsmYNygVLSPk1pEfDoY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e/go.mod h1:085qFyf2+XaZlRdCgKNCIZ3afY2p4HHZdoIRpId8F4A=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e h1:ztQaXfzEXTmCBvbtWYRhJxW+0iJcz2qXfd38/e9l7bA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8=
|
||||
google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||
|
||||
@@ -19,7 +19,14 @@ func NewTestingEngine(facts *entities.PodmanConfig) (ientities.TestingEngine, er
|
||||
r, err := NewLibpodTestingRuntime(facts.FlagSet, facts)
|
||||
return r, err
|
||||
case entities.TunnelMode:
|
||||
ctx, err := bindings.NewConnectionWithIdentity(context.Background(), facts.URI, facts.Identity, facts.MachineMode)
|
||||
ctx, err := bindings.NewConnectionWithOptions(context.Background(), bindings.Options{
|
||||
URI: facts.URI,
|
||||
Identity: facts.Identity,
|
||||
TLSCertFile: facts.TLSCertFile,
|
||||
TLSKeyFile: facts.TLSKeyFile,
|
||||
TLSCAFile: facts.TLSCAFile,
|
||||
Machine: facts.MachineMode,
|
||||
})
|
||||
return &tunnel.TestingEngine{ClientCtx: ctx}, err
|
||||
}
|
||||
return nil, fmt.Errorf("runtime mode '%v' is not supported", facts.EngineMode)
|
||||
|
||||
@@ -4,6 +4,7 @@ package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
@@ -22,6 +23,7 @@ import (
|
||||
"github.com/containers/podman/v5/pkg/api/server/idle"
|
||||
"github.com/containers/podman/v5/pkg/api/types"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities"
|
||||
"github.com/containers/podman/v5/pkg/util/tlsutil"
|
||||
"github.com/coreos/go-systemd/v22/daemon"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/schema"
|
||||
@@ -38,6 +40,9 @@ type APIServer struct {
|
||||
CorsHeaders string // Inject Cross-Origin Resource Sharing (CORS) headers
|
||||
PProfAddr string // Binding network address for pprof profiles
|
||||
idleTracker *idle.Tracker // Track connections to support idle shutdown
|
||||
tlsCertFile string // TLS serving certificate PEM file
|
||||
tlsKeyFile string // TLS serving certificate private key PEM file
|
||||
tlsClientCAFile string // TLS client certifiicate CA bundle PEM file
|
||||
}
|
||||
|
||||
// Number of seconds to wait for next request, if exceeded shutdown server
|
||||
@@ -76,10 +81,13 @@ func newServer(runtime *libpod.Runtime, listener net.Listener, opts entities.Ser
|
||||
Handler: router,
|
||||
IdleTimeout: opts.Timeout * 2,
|
||||
},
|
||||
CorsHeaders: opts.CorsHeaders,
|
||||
Listener: listener,
|
||||
PProfAddr: opts.PProfAddr,
|
||||
idleTracker: tracker,
|
||||
CorsHeaders: opts.CorsHeaders,
|
||||
Listener: listener,
|
||||
PProfAddr: opts.PProfAddr,
|
||||
idleTracker: tracker,
|
||||
tlsCertFile: opts.TLSCertFile,
|
||||
tlsKeyFile: opts.TLSKeyFile,
|
||||
tlsClientCAFile: opts.TLSClientCAFile,
|
||||
}
|
||||
|
||||
server.BaseContext = func(l net.Listener) context.Context {
|
||||
@@ -90,6 +98,18 @@ func newServer(runtime *libpod.Runtime, listener net.Listener, opts entities.Ser
|
||||
return ctx
|
||||
}
|
||||
|
||||
if opts.TLSClientCAFile != "" {
|
||||
logrus.Debugf("will validate client certs against %s", opts.TLSClientCAFile)
|
||||
pool, err := tlsutil.ReadCertBundle(opts.TLSClientCAFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
server.TLSConfig = &tls.Config{
|
||||
ClientCAs: pool,
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
}
|
||||
}
|
||||
|
||||
// Capture panics and print stack traces for diagnostics,
|
||||
// additionally process X-Reference-Id Header to support event correlation
|
||||
router.Use(panicHandler(), referenceIDHandler())
|
||||
@@ -217,7 +237,15 @@ func (s *APIServer) Serve() error {
|
||||
errChan := make(chan error, 1)
|
||||
s.setupSystemd()
|
||||
go func() {
|
||||
err := s.Server.Serve(s.Listener)
|
||||
var err error
|
||||
if s.tlsClientCAFile != "" || (s.tlsCertFile != "" && s.tlsKeyFile != "") {
|
||||
if s.tlsCertFile != "" && s.tlsKeyFile != "" {
|
||||
logrus.Debugf("serving TLS with cert %s and key %s", s.tlsCertFile, s.tlsKeyFile)
|
||||
}
|
||||
err = s.Server.ServeTLS(s.Listener, s.tlsCertFile, s.tlsKeyFile)
|
||||
} else {
|
||||
err = s.Server.Serve(s.Listener)
|
||||
}
|
||||
if err != nil && err != http.ErrServerClosed {
|
||||
errChan <- fmt.Errorf("failed to start API service: %w", err)
|
||||
return
|
||||
|
||||
@@ -3,6 +3,7 @@ package bindings
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -17,6 +18,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/containers/podman/v5/pkg/util/tlsutil"
|
||||
"github.com/containers/podman/v5/version"
|
||||
"github.com/kevinburke/ssh_config"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -33,6 +35,7 @@ type APIResponse struct {
|
||||
type Connection struct {
|
||||
URI *url.URL
|
||||
Client *http.Client
|
||||
tls bool
|
||||
}
|
||||
|
||||
type valueKey string
|
||||
@@ -89,7 +92,7 @@ func JoinURL(elements ...string) string {
|
||||
|
||||
// NewConnection creates a new service connection without an identity
|
||||
func NewConnection(ctx context.Context, uri string) (context.Context, error) {
|
||||
return NewConnectionWithIdentity(ctx, uri, "", false)
|
||||
return NewConnectionWithOptions(ctx, Options{URI: uri})
|
||||
}
|
||||
|
||||
// NewConnectionWithIdentity takes a URI as a string and returns a context with the
|
||||
@@ -101,14 +104,31 @@ func NewConnection(ctx context.Context, uri string) (context.Context, error) {
|
||||
// or unix:///run/podman/podman.sock
|
||||
// or ssh://<user>@<host>[:port]/run/podman/podman.sock
|
||||
func NewConnectionWithIdentity(ctx context.Context, uri string, identity string, machine bool) (context.Context, error) {
|
||||
var err error
|
||||
if v, found := os.LookupEnv("CONTAINER_HOST"); found && uri == "" {
|
||||
uri = v
|
||||
}
|
||||
return NewConnectionWithOptions(ctx, Options{URI: uri, Identity: identity, Machine: machine})
|
||||
}
|
||||
|
||||
if v, found := os.LookupEnv("CONTAINER_SSHKEY"); found && len(identity) == 0 {
|
||||
identity = v
|
||||
type Options struct {
|
||||
URI string
|
||||
Identity string
|
||||
TLSCertFile string
|
||||
TLSKeyFile string
|
||||
TLSCAFile string
|
||||
Machine bool
|
||||
}
|
||||
|
||||
func orEnv(s string, env string) string {
|
||||
if len(s) != 0 {
|
||||
return s
|
||||
}
|
||||
s, _ = os.LookupEnv(env)
|
||||
return s
|
||||
}
|
||||
|
||||
func NewConnectionWithOptions(ctx context.Context, opts Options) (context.Context, error) {
|
||||
var err error
|
||||
|
||||
uri := orEnv(opts.URI, "CONTAINER_HOST")
|
||||
identity := orEnv(opts.Identity, "CONTAINER_SSHKEY")
|
||||
|
||||
_url, err := url.Parse(uri)
|
||||
if err != nil {
|
||||
@@ -119,7 +139,7 @@ func NewConnectionWithIdentity(ctx context.Context, uri string, identity string,
|
||||
var connection Connection
|
||||
switch _url.Scheme {
|
||||
case "ssh":
|
||||
conn, err := sshClient(_url, uri, identity, machine)
|
||||
conn, err := sshClient(_url, uri, identity, opts.Machine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -135,7 +155,7 @@ func NewConnectionWithIdentity(ctx context.Context, uri string, identity string,
|
||||
if !strings.HasPrefix(uri, "tcp://") {
|
||||
return nil, errors.New("tcp URIs should begin with tcp://")
|
||||
}
|
||||
conn, err := tcpClient(_url)
|
||||
conn, err := tcpClient(_url, opts.TLSCertFile, opts.TLSKeyFile, opts.TLSCAFile)
|
||||
if err != nil {
|
||||
return nil, newConnectError(err)
|
||||
}
|
||||
@@ -151,7 +171,7 @@ func NewConnectionWithIdentity(ctx context.Context, uri string, identity string,
|
||||
}
|
||||
ctx = context.WithValue(ctx, versionKey, serviceVersion)
|
||||
|
||||
ctx = context.WithValue(ctx, machineModeKey, machine)
|
||||
ctx = context.WithValue(ctx, machineModeKey, opts.Machine)
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
@@ -288,7 +308,7 @@ func sshClient(_url *url.URL, uri string, identity string, machine bool) (Connec
|
||||
return connection, nil
|
||||
}
|
||||
|
||||
func tcpClient(_url *url.URL) (Connection, error) {
|
||||
func tcpClient(_url *url.URL, tlsCertFile, tlsKeyFile, tlsCAFile string) (Connection, error) {
|
||||
connection := Connection{
|
||||
URI: _url,
|
||||
}
|
||||
@@ -320,11 +340,34 @@ func tcpClient(_url *url.URL) (Connection, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
transport := http.Transport{
|
||||
DialContext: dialContext,
|
||||
DisableCompression: true,
|
||||
}
|
||||
if len(tlsCAFile) != 0 || len(tlsCertFile) != 0 || len(tlsKeyFile) != 0 {
|
||||
logrus.Debugf("using TLS cert=%s key=%s ca=%s", tlsCertFile, tlsKeyFile, tlsCAFile)
|
||||
transport.TLSClientConfig = &tls.Config{}
|
||||
connection.tls = true
|
||||
}
|
||||
if len(tlsCAFile) != 0 {
|
||||
pool, err := tlsutil.ReadCertBundle(tlsCAFile)
|
||||
if err != nil {
|
||||
return connection, fmt.Errorf("unable to read CA bundle: %w", err)
|
||||
}
|
||||
transport.TLSClientConfig.RootCAs = pool
|
||||
}
|
||||
if (len(tlsCertFile) == 0) != (len(tlsKeyFile) == 0) {
|
||||
return connection, fmt.Errorf("TLS Key and Certificate must both or neither be provided")
|
||||
}
|
||||
if len(tlsCertFile) != 0 && len(tlsKeyFile) != 0 {
|
||||
keyPair, err := tls.LoadX509KeyPair(tlsCertFile, tlsKeyFile)
|
||||
if err != nil {
|
||||
return connection, fmt.Errorf("unable to read TLS key pair: %w", err)
|
||||
}
|
||||
transport.TLSClientConfig.Certificates = append(transport.TLSClientConfig.Certificates, keyPair)
|
||||
}
|
||||
connection.Client = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: dialContext,
|
||||
DisableCompression: true,
|
||||
},
|
||||
Transport: &transport,
|
||||
}
|
||||
return connection, nil
|
||||
}
|
||||
@@ -405,8 +448,14 @@ func (c *Connection) DoRequest(ctx context.Context, httpBody io.Reader, httpMeth
|
||||
|
||||
baseURL := "http://d"
|
||||
if c.URI.Scheme == "tcp" {
|
||||
var scheme string
|
||||
if c.tls {
|
||||
scheme = "https"
|
||||
} else {
|
||||
scheme = "http"
|
||||
}
|
||||
// Allow path prefixes for tcp connections to match Docker behavior
|
||||
baseURL = "http://" + c.URI.Host + c.URI.Path
|
||||
baseURL = scheme + "://" + c.URI.Host + c.URI.Path
|
||||
}
|
||||
uri := fmt.Sprintf(baseURL+"/v%s/libpod"+endpoint, params...)
|
||||
logrus.Debugf("DoRequest Method: %s URI: %v", httpMethod, uri)
|
||||
|
||||
@@ -3,6 +3,7 @@ package containers
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -548,9 +549,11 @@ func newUpgradeRequest(ctx context.Context, conn *bindings.Connection, body io.R
|
||||
"Upgrade": []string{"tcp"},
|
||||
}
|
||||
|
||||
// FIXME: This is one giant race condition. Let's hope no-one uses this same client until we're done!
|
||||
var socket net.Conn
|
||||
socketSet := false
|
||||
dialContext := conn.Client.Transport.(*http.Transport).DialContext
|
||||
tlsConfig := conn.Client.Transport.(*http.Transport).TLSClientConfig
|
||||
t := &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
c, err := dialContext(ctx, network, address)
|
||||
@@ -563,7 +566,33 @@ func newUpgradeRequest(ctx context.Context, conn *bindings.Connection, body io.R
|
||||
}
|
||||
return c, err
|
||||
},
|
||||
DialTLSContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
c, err := dialContext(ctx, network, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var cfg *tls.Config
|
||||
if tlsConfig == nil {
|
||||
cfg = new(tls.Config)
|
||||
} else {
|
||||
cfg = tlsConfig.Clone()
|
||||
}
|
||||
if cfg.ServerName == "" {
|
||||
var firstTLSHost string
|
||||
if firstTLSHost, _, err = net.SplitHostPort(address); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.ServerName = firstTLSHost
|
||||
}
|
||||
c = tls.Client(c, cfg)
|
||||
if !socketSet {
|
||||
socket = c
|
||||
socketSet = true
|
||||
}
|
||||
return c, err
|
||||
},
|
||||
IdleConnTimeout: time.Duration(0),
|
||||
TLSClientConfig: tlsConfig,
|
||||
}
|
||||
conn.Client.Transport = t
|
||||
response, err := conn.DoRequest(ctx, body, http.MethodPost, path, params, headers)
|
||||
|
||||
@@ -37,6 +37,9 @@ type PodmanConfig struct {
|
||||
HooksDir []string
|
||||
CdiSpecDirs []string
|
||||
Identity string // ssh identity for connecting to server
|
||||
TLSCertFile string // tls client cert for connecting to server
|
||||
TLSKeyFile string // tls client cert private key for connection to server
|
||||
TLSCAFile string // tls certificate authority to verify server connection
|
||||
IsRenumber bool // Is this a system renumber command? If so, a number of checks will be relaxed
|
||||
IsReset bool // Is this a system reset command? If so, a number of checks will be skipped/omitted
|
||||
MaxWorks int // maximum number of parallel threads
|
||||
|
||||
@@ -9,10 +9,13 @@ import (
|
||||
|
||||
// ServiceOptions provides the input for starting an API and sidecar pprof services
|
||||
type ServiceOptions struct {
|
||||
CorsHeaders string // Cross-Origin Resource Sharing (CORS) headers
|
||||
PProfAddr string // Network address to bind pprof profiles service
|
||||
Timeout time.Duration // Duration of inactivity the service should wait before shutting down
|
||||
URI string // Path to unix domain socket service should listen on
|
||||
CorsHeaders string // Cross-Origin Resource Sharing (CORS) headers
|
||||
PProfAddr string // Network address to bind pprof profiles service
|
||||
Timeout time.Duration // Duration of inactivity the service should wait before shutting down
|
||||
URI string // Path to unix domain socket service should listen on
|
||||
TLSCertFile string // Path to serving certificate PEM file
|
||||
TLSKeyFile string // Path to serving certificate key PEM file
|
||||
TLSClientCAFile string // Path to client certificate authority
|
||||
}
|
||||
|
||||
// SystemCheckOptions provides options for checking storage consistency.
|
||||
|
||||
@@ -18,7 +18,14 @@ func NewContainerEngine(facts *entities.PodmanConfig) (entities.ContainerEngine,
|
||||
r, err := NewLibpodRuntime(facts.FlagSet, facts)
|
||||
return r, err
|
||||
case entities.TunnelMode:
|
||||
ctx, err := bindings.NewConnectionWithIdentity(context.Background(), facts.URI, facts.Identity, facts.MachineMode)
|
||||
ctx, err := bindings.NewConnectionWithOptions(context.Background(), bindings.Options{
|
||||
URI: facts.URI,
|
||||
Identity: facts.Identity,
|
||||
TLSCertFile: facts.TLSCertFile,
|
||||
TLSKeyFile: facts.TLSKeyFile,
|
||||
TLSCAFile: facts.TLSCAFile,
|
||||
Machine: facts.MachineMode,
|
||||
})
|
||||
return &tunnel.ContainerEngine{ClientCtx: ctx}, err
|
||||
}
|
||||
return nil, fmt.Errorf("runtime mode '%v' is not supported", facts.EngineMode)
|
||||
@@ -32,7 +39,14 @@ func NewImageEngine(facts *entities.PodmanConfig) (entities.ImageEngine, error)
|
||||
return r, err
|
||||
case entities.TunnelMode:
|
||||
// TODO: look at me!
|
||||
ctx, err := bindings.NewConnectionWithIdentity(context.Background(), facts.URI, facts.Identity, facts.MachineMode)
|
||||
ctx, err := bindings.NewConnectionWithOptions(context.Background(), bindings.Options{
|
||||
URI: facts.URI,
|
||||
Identity: facts.Identity,
|
||||
TLSCertFile: facts.TLSCertFile,
|
||||
TLSKeyFile: facts.TLSKeyFile,
|
||||
TLSCAFile: facts.TLSCAFile,
|
||||
Machine: facts.MachineMode,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %s", err, facts.URI)
|
||||
}
|
||||
|
||||
@@ -17,13 +17,20 @@ var (
|
||||
connection *context.Context
|
||||
)
|
||||
|
||||
func newConnection(uri string, identity, farmNodeName string, machine bool) (context.Context, error) {
|
||||
func newConnection(uri string, identity, tlsCertFile, tlsKeyFile, tlsCAFile, farmNodeName string, machine bool) (context.Context, error) {
|
||||
connectionMutex.Lock()
|
||||
defer connectionMutex.Unlock()
|
||||
|
||||
// if farmNodeName given, then create a connection with the node so that we can send builds there
|
||||
if connection == nil || farmNodeName != "" {
|
||||
ctx, err := bindings.NewConnectionWithIdentity(context.Background(), uri, identity, machine)
|
||||
ctx, err := bindings.NewConnectionWithOptions(context.Background(), bindings.Options{
|
||||
URI: uri,
|
||||
Identity: identity,
|
||||
TLSCertFile: tlsCertFile,
|
||||
TLSKeyFile: tlsKeyFile,
|
||||
TLSCAFile: tlsCAFile,
|
||||
Machine: machine,
|
||||
})
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
@@ -37,7 +44,7 @@ func NewContainerEngine(facts *entities.PodmanConfig) (entities.ContainerEngine,
|
||||
case entities.ABIMode:
|
||||
return nil, fmt.Errorf("direct runtime not supported")
|
||||
case entities.TunnelMode:
|
||||
ctx, err := newConnection(facts.URI, facts.Identity, "", facts.MachineMode)
|
||||
ctx, err := newConnection(facts.URI, facts.Identity, facts.TLSCertFile, facts.TLSKeyFile, facts.TLSCAFile, "", facts.MachineMode)
|
||||
return &tunnel.ContainerEngine{ClientCtx: ctx}, err
|
||||
}
|
||||
return nil, fmt.Errorf("runtime mode '%v' is not supported", facts.EngineMode)
|
||||
@@ -49,7 +56,7 @@ func NewImageEngine(facts *entities.PodmanConfig) (entities.ImageEngine, error)
|
||||
case entities.ABIMode:
|
||||
return nil, fmt.Errorf("direct image runtime not supported")
|
||||
case entities.TunnelMode:
|
||||
ctx, err := newConnection(facts.URI, facts.Identity, facts.FarmNodeName, facts.MachineMode)
|
||||
ctx, err := newConnection(facts.URI, facts.Identity, facts.TLSCertFile, facts.TLSKeyFile, facts.TLSCAFile, facts.FarmNodeName, facts.MachineMode)
|
||||
return &tunnel.ImageEngine{ClientCtx: ctx, FarmNode: tunnel.FarmNode{NodeName: facts.FarmNodeName}}, err
|
||||
}
|
||||
return nil, fmt.Errorf("runtime mode '%v' is not supported", facts.EngineMode)
|
||||
|
||||
32
pkg/util/tlsutil/tls.go
Normal file
32
pkg/util/tlsutil/tls.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package tlsutil
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func ReadCertBundle(path string) (*x509.CertPool, error) {
|
||||
pool := x509.NewCertPool()
|
||||
caPEM, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading cert bundle %s: %w", path, err)
|
||||
}
|
||||
for ix := 0; len(caPEM) != 0; ix++ {
|
||||
var caDER *pem.Block
|
||||
caDER, caPEM = pem.Decode(caPEM)
|
||||
if caDER == nil {
|
||||
return nil, fmt.Errorf("reading cert bundle %s: non-PEM data found", path)
|
||||
}
|
||||
if caDER.Type != "CERTIFICATE" {
|
||||
return nil, fmt.Errorf("reading cert bundle %s: non-certificate type `%s` PEM data found", path, caDER.Type)
|
||||
}
|
||||
caCert, err := x509.ParseCertificate(caDER.Bytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading cert bundle %s: parsing item %d: %w", path, ix, err)
|
||||
}
|
||||
pool.AddCert(caCert)
|
||||
}
|
||||
return pool, nil
|
||||
}
|
||||
@@ -6,7 +6,11 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
crand "crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -68,8 +72,10 @@ type PodmanTestIntegration struct {
|
||||
TmpDir string
|
||||
}
|
||||
|
||||
var GlobalTmpDir string // Single top-level tmpdir for all tests
|
||||
var LockTmpDir string
|
||||
var (
|
||||
GlobalTmpDir string // Single top-level tmpdir for all tests
|
||||
LockTmpDir string
|
||||
)
|
||||
|
||||
// PodmanSessionIntegration struct for command line session
|
||||
type PodmanSessionIntegration struct {
|
||||
@@ -278,8 +284,18 @@ func getPodmanBinary(cwd string) string {
|
||||
return podmanBinary
|
||||
}
|
||||
|
||||
type PodmanTestCreateUtilTarget string
|
||||
|
||||
const (
|
||||
PodmanTestCreateUtilTargetLocal = ""
|
||||
PodmanTestCreateUtilTargetUnix = "unix"
|
||||
PodmanTestCreateUtilTargetTCP = "tcp"
|
||||
PodmanTestCreateUtilTargetTLS = "tls"
|
||||
PodmanTestCreateUtilTargetMTLS = "mtls"
|
||||
)
|
||||
|
||||
// PodmanTestCreate creates a PodmanTestIntegration instance for the tests
|
||||
func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
|
||||
func PodmanTestCreateUtil(tempDir string, target PodmanTestCreateUtilTarget) *PodmanTestIntegration {
|
||||
host := GetHostDistributionInfo()
|
||||
cwd, _ := os.Getwd()
|
||||
|
||||
@@ -364,7 +380,7 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
|
||||
PodmanBinary: podmanBinary,
|
||||
RemotePodmanBinary: podmanRemoteBinary,
|
||||
TempDir: tempDir,
|
||||
RemoteTest: remote,
|
||||
RemoteTest: target != PodmanTestCreateUtilTargetLocal,
|
||||
ImageCacheFS: storageFs,
|
||||
ImageCacheDir: ImageCacheDir,
|
||||
NetworkBackend: networkBackend,
|
||||
@@ -383,14 +399,20 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
|
||||
Host: host,
|
||||
}
|
||||
|
||||
if remote {
|
||||
var pathPrefix string
|
||||
var pathPrefix string
|
||||
switch target {
|
||||
case PodmanTestCreateUtilTargetLocal:
|
||||
default:
|
||||
if !isRootless() {
|
||||
pathPrefix = "/run/podman/podman"
|
||||
Expect(os.MkdirAll(pathPrefix, 0o700)).To(Succeed())
|
||||
} else {
|
||||
runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
|
||||
pathPrefix = filepath.Join(runtimeDir, "podman")
|
||||
}
|
||||
}
|
||||
switch target {
|
||||
case PodmanTestCreateUtilTargetUnix:
|
||||
// We want to avoid collisions in socket paths, but using the
|
||||
// socket directly for a collision check doesn’t work; bind(2) on AF_UNIX
|
||||
// creates the file, and we need to pass a unique path now before the bind(2)
|
||||
@@ -404,13 +426,153 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
|
||||
lockFile.Close()
|
||||
p.RemoteSocketLock = lockPath
|
||||
p.RemoteSocket = fmt.Sprintf("unix://%s-%s.sock", pathPrefix, uuid)
|
||||
p.RemoteSocketScheme = "unix"
|
||||
break
|
||||
}
|
||||
GinkgoLogr.Error(err, "RemoteSocket collision")
|
||||
tries++
|
||||
if tries >= 1000 {
|
||||
panic("Too many RemoteSocket collisions")
|
||||
}
|
||||
}
|
||||
case PodmanTestCreateUtilTargetTCP, PodmanTestCreateUtilTargetTLS, PodmanTestCreateUtilTargetMTLS:
|
||||
tries := 0
|
||||
for {
|
||||
uuid := stringid.GenerateRandomID()
|
||||
lockPath := fmt.Sprintf("%s-%s.sock-lock", pathPrefix, uuid)
|
||||
lockFile, err := os.OpenFile(lockPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0700)
|
||||
if err == nil {
|
||||
lockFile.Close()
|
||||
p.RemoteSocketLock = lockPath
|
||||
lis, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err == nil {
|
||||
defer lis.Close()
|
||||
p.RemoteSocket = fmt.Sprintf("tcp://%s", lis.Addr())
|
||||
p.RemoteSocketScheme = "tcp"
|
||||
break
|
||||
}
|
||||
}
|
||||
GinkgoLogr.Error(err, "RemoteSocket collision")
|
||||
tries++
|
||||
if tries >= 1000 {
|
||||
panic("Too many RemoteSocket collisions")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
caKeyPath := filepath.Join(p.TempDir, "tls.ca.key")
|
||||
caCertPath := filepath.Join(p.TempDir, "tls.ca.crt")
|
||||
srvCertPath := filepath.Join(p.TempDir, "tls.srv.crt")
|
||||
srvKeyPath := filepath.Join(p.TempDir, "tls.srv.key")
|
||||
clientCertPath := filepath.Join(p.TempDir, "tls.client.crt")
|
||||
clientKeyPath := filepath.Join(p.TempDir, "tls.client.key")
|
||||
switch target {
|
||||
case PodmanTestCreateUtilTargetTLS, PodmanTestCreateUtilTargetMTLS:
|
||||
GinkgoLogr.Info("Generating test TLS certs", "now", time.Now(), "tmpdir", p.TempDir)
|
||||
now := time.Now()
|
||||
caPriv, err := rsa.GenerateKey(crand.Reader, 2048)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
caTmpl := x509.Certificate{
|
||||
NotBefore: now,
|
||||
NotAfter: now.Add(5 * time.Minute),
|
||||
IsCA: true,
|
||||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||
BasicConstraintsValid: true,
|
||||
|
||||
DNSNames: []string{"localhost"},
|
||||
IPAddresses: []net.IP{net.ParseIP("127.0.0.1")},
|
||||
}
|
||||
caCertDER, err := x509.CreateCertificate(crand.Reader, &caTmpl, &caTmpl, &caPriv.PublicKey, caPriv)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
caCertPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: caCertDER,
|
||||
})
|
||||
caKeyDER, err := x509.MarshalPKCS8PrivateKey(caPriv)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
caKeyPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: caKeyDER,
|
||||
})
|
||||
err = os.WriteFile(caCertPath, caCertPEM, 0o600)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = os.WriteFile(caKeyPath, caKeyPEM, 0o600)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
caCert, err := x509.ParseCertificate(caCertDER)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
srvPriv, err := rsa.GenerateKey(crand.Reader, 2048)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
srvTmpl := x509.Certificate{
|
||||
NotBefore: now,
|
||||
NotAfter: now.Add(5 * time.Minute),
|
||||
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||
BasicConstraintsValid: true,
|
||||
DNSNames: []string{"localhost"},
|
||||
IPAddresses: []net.IP{net.ParseIP("127.0.0.1")},
|
||||
}
|
||||
srvCertDER, err := x509.CreateCertificate(crand.Reader, &srvTmpl, caCert, &srvPriv.PublicKey, caPriv)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
srvCertPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: srvCertDER,
|
||||
})
|
||||
srvKeyDER, err := x509.MarshalPKCS8PrivateKey(srvPriv)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
srvKeyPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: srvKeyDER,
|
||||
})
|
||||
err = os.WriteFile(srvCertPath, srvCertPEM, 0o600)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = os.WriteFile(srvKeyPath, srvKeyPEM, 0o600)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
p.RemoteTLSServerCAFile = caCertPath
|
||||
p.RemoteTLSServerCAPool = x509.NewCertPool()
|
||||
p.RemoteTLSServerCAPool.AddCert(caCert)
|
||||
p.RemoteTLSServerCertFile = srvCertPath
|
||||
p.RemoteTLSServerKeyFile = srvKeyPath
|
||||
if target == PodmanTestCreateUtilTargetMTLS {
|
||||
clientPriv, err := rsa.GenerateKey(crand.Reader, 2048)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
clientTmpl := x509.Certificate{
|
||||
NotBefore: now,
|
||||
NotAfter: now.Add(5 * time.Minute),
|
||||
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
clientCertDER, err := x509.CreateCertificate(crand.Reader, &clientTmpl, caCert, &clientPriv.PublicKey, caPriv)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
clientCertPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: clientCertDER,
|
||||
})
|
||||
clientKeyDER, err := x509.MarshalPKCS8PrivateKey(clientPriv)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
clientCert, err := x509.ParseCertificate(clientCertDER)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
clientKeyPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: clientKeyDER,
|
||||
})
|
||||
err = os.WriteFile(clientCertPath, clientCertPEM, 0o600)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = os.WriteFile(clientKeyPath, clientKeyPEM, 0o600)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
p.RemoteTLSClientCAFile = caCertPath
|
||||
p.RemoteTLSServerCAPool = x509.NewCertPool()
|
||||
p.RemoteTLSServerCAPool.AddCert(caCert)
|
||||
p.RemoteTLSClientCertFile = clientCertPath
|
||||
p.RemoteTLSClientKeyFile = clientKeyPath
|
||||
p.RemoteTLSClientCerts = []tls.Certificate{{
|
||||
Certificate: [][]byte{clientCertDER},
|
||||
PrivateKey: clientPriv,
|
||||
Leaf: clientCert,
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
// Set up registries.conf ENV variable
|
||||
@@ -1173,7 +1335,7 @@ func (p *PodmanTestIntegration) PodmanNoCache(args []string) *PodmanSessionInteg
|
||||
}
|
||||
|
||||
func PodmanTestSetup(tempDir string) *PodmanTestIntegration {
|
||||
return PodmanTestCreateUtil(tempDir, false)
|
||||
return PodmanTestCreateUtil(tempDir, PodmanTestCreateUtilTargetLocal)
|
||||
}
|
||||
|
||||
// PodmanNoEvents calls the Podman command without an imagecache and without an
|
||||
@@ -1190,7 +1352,17 @@ func (p *PodmanTestIntegration) PodmanNoEvents(args []string) *PodmanSessionInte
|
||||
func (p *PodmanTestIntegration) makeOptions(args []string, options PodmanExecOptions) []string {
|
||||
if p.RemoteTest {
|
||||
if !slices.Contains(args, "--remote") {
|
||||
return append([]string{"--remote", "--url", p.RemoteSocket}, args...)
|
||||
remoteArgs := []string{"--remote", "--url", p.RemoteSocket}
|
||||
if p.RemoteTLSServerCAFile != "" {
|
||||
remoteArgs = append(remoteArgs, "--tls-ca", p.RemoteTLSServerCAFile)
|
||||
}
|
||||
if p.RemoteTLSClientCertFile != "" {
|
||||
remoteArgs = append(remoteArgs, "--tls-cert", p.RemoteTLSClientCertFile)
|
||||
}
|
||||
if p.RemoteTLSClientKeyFile != "" {
|
||||
remoteArgs = append(remoteArgs, "--tls-key", p.RemoteTLSClientKeyFile)
|
||||
}
|
||||
return append(remoteArgs, args...)
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build linux || freebsd
|
||||
//go:build !remote_testing && (linux || freebsd)
|
||||
|
||||
package integration
|
||||
|
||||
@@ -26,6 +26,11 @@ var _ = Describe("podman image scp", func() {
|
||||
if _, err := os.Stat(filepath.Join(homedir.Get(), ".ssh", "known_hosts")); err != nil {
|
||||
Skip("known_hosts does not exist or is not accessible")
|
||||
}
|
||||
|
||||
ensureImage := podmanTest.Podman([]string{"pull", "-q", ALPINE})
|
||||
ensureImage.WaitWithDefaultTimeout()
|
||||
Expect(ensureImage).Should(ExitCleanly())
|
||||
|
||||
cmd := []string{"system", "connection", "add",
|
||||
"--default",
|
||||
"QA",
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
)
|
||||
|
||||
var _ = Describe("Podman Info", func() {
|
||||
|
||||
It("podman info --format json", func() {
|
||||
tests := []struct {
|
||||
input string
|
||||
@@ -108,7 +107,12 @@ var _ = Describe("Podman Info", func() {
|
||||
session := podmanTest.Podman([]string{"info", "--format", "{{.Host.RemoteSocket.Path}}"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
Expect(session.OutputToString()).To(MatchRegexp("/run/.*podman.*sock"))
|
||||
switch podmanTest.RemoteSocketScheme {
|
||||
case "unix":
|
||||
Expect(session.OutputToString()).To(MatchRegexp("/run/.*podman.*sock"))
|
||||
case "tcp":
|
||||
Expect(session.OutputToString()).To(MatchRegexp("tcp://127.0.0.1:.*"))
|
||||
}
|
||||
|
||||
session = podmanTest.Podman([]string{"info", "--format", "{{.Host.ServiceIsRemote}}"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
@@ -125,7 +129,6 @@ var _ = Describe("Podman Info", func() {
|
||||
Expect(session).Should(ExitCleanly())
|
||||
Expect(session.OutputToString()).To(Equal("true"))
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
It("Podman info must contain cgroupControllers with RelevantControllers", func() {
|
||||
|
||||
@@ -18,6 +18,8 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var RemoteTestingTarget = PodmanTestCreateUtilTarget(os.Getenv("REMOTEINTEGRATION_TRANSPORT"))
|
||||
|
||||
func IsRemote() bool {
|
||||
return true
|
||||
}
|
||||
@@ -53,11 +55,6 @@ func (p *PodmanTestIntegration) setRegistriesConfigEnv(b []byte) {
|
||||
func resetRegistriesConfigEnv() {
|
||||
os.Setenv("CONTAINERS_REGISTRIES_CONF", "")
|
||||
}
|
||||
func PodmanTestCreate(tempDir string) *PodmanTestIntegration {
|
||||
pti := PodmanTestCreateUtil(tempDir, true)
|
||||
pti.StartRemoteService()
|
||||
return pti
|
||||
}
|
||||
|
||||
func (p *PodmanTestIntegration) StartRemoteService() {
|
||||
if !isRootless() {
|
||||
@@ -70,10 +67,26 @@ func (p *PodmanTestIntegration) StartRemoteService() {
|
||||
args = append(args, "--log-level", "trace")
|
||||
}
|
||||
remoteSocket := p.RemoteSocket
|
||||
args = append(args, "system", "service", "--time", "0", remoteSocket)
|
||||
args = append(args, "system", "service", "--time", "0")
|
||||
|
||||
if p.RemoteTLSClientCAFile != "" {
|
||||
args = append(args, "--tls-client-ca", p.RemoteTLSClientCAFile)
|
||||
}
|
||||
if p.RemoteTLSServerCertFile != "" {
|
||||
args = append(args, "--tls-cert", p.RemoteTLSServerCertFile)
|
||||
}
|
||||
if p.RemoteTLSServerKeyFile != "" {
|
||||
args = append(args, "--tls-key", p.RemoteTLSServerKeyFile)
|
||||
}
|
||||
|
||||
args = append(args, remoteSocket)
|
||||
|
||||
podmanOptions := getRemoteOptions(p, args)
|
||||
cacheOptions := []string{"--storage-opt",
|
||||
fmt.Sprintf("%s.imagestore=%s", p.PodmanTest.ImageCacheFS, p.PodmanTest.ImageCacheDir)}
|
||||
cacheOptions := []string{
|
||||
"--storage-opt",
|
||||
fmt.Sprintf("%s.imagestore=%s", p.PodmanTest.ImageCacheFS, p.PodmanTest.ImageCacheDir),
|
||||
}
|
||||
|
||||
podmanOptions = append(cacheOptions, podmanOptions...)
|
||||
command := exec.Command(p.PodmanBinary, podmanOptions...)
|
||||
command.Stdout = GinkgoWriter
|
||||
@@ -111,11 +124,18 @@ func getRemoteOptions(p *PodmanTestIntegration, args []string) []string {
|
||||
networkDir := p.NetworkConfigDir
|
||||
podmanOptions := strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --network-config-dir %s --network-backend %s --cgroup-manager %s --tmpdir %s --events-backend %s --db-backend %s",
|
||||
p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, networkDir, p.NetworkBackend.ToString(), p.CgroupManager, p.TmpDir, "file", p.DatabaseBackend), " ")
|
||||
|
||||
podmanOptions = append(podmanOptions, strings.Split(p.StorageOptions, " ")...)
|
||||
podmanOptions = append(podmanOptions, args...)
|
||||
return podmanOptions
|
||||
}
|
||||
|
||||
func PodmanTestCreate(tempDir string) *PodmanTestIntegration {
|
||||
pti := PodmanTestCreateUtil(tempDir, RemoteTestingTarget)
|
||||
pti.StartRemoteService()
|
||||
return pti
|
||||
}
|
||||
|
||||
// RestoreArtifact puts the cached image into our test store
|
||||
func (p *PodmanTestIntegration) RestoreArtifact(image string) error {
|
||||
tarball := imageTarPath(image)
|
||||
@@ -139,7 +159,7 @@ func (p *PodmanTestIntegration) DelayForService() error {
|
||||
var err error
|
||||
var conn net.Conn
|
||||
for i := 0; i < 100; i++ {
|
||||
conn, err = net.Dial("unix", strings.TrimPrefix(p.RemoteSocket, "unix:"))
|
||||
conn, err = net.Dial(p.RemoteSocketScheme, strings.TrimPrefix(p.RemoteSocket, p.RemoteSocketScheme+"://"))
|
||||
if err == nil {
|
||||
conn.Close()
|
||||
return nil
|
||||
|
||||
@@ -26,6 +26,12 @@ func (p *PodmanTestIntegration) PodmanWithOptions(options PodmanExecOptions, arg
|
||||
return &PodmanSessionIntegration{podmanSession}
|
||||
}
|
||||
|
||||
func PodmanTestCreate(tempDir string) *PodmanTestIntegration {
|
||||
pti := PodmanTestCreateUtil(tempDir, PodmanTestCreateUtilTargetLocal)
|
||||
pti.StartRemoteService()
|
||||
return pti
|
||||
}
|
||||
|
||||
func (p *PodmanTestIntegration) setDefaultRegistriesConfigEnv() {
|
||||
defaultFile := "registries.conf"
|
||||
if UsingCacheRegistry() {
|
||||
@@ -47,10 +53,6 @@ func resetRegistriesConfigEnv() {
|
||||
os.Setenv("CONTAINERS_REGISTRIES_CONF", "")
|
||||
}
|
||||
|
||||
func PodmanTestCreate(tempDir string) *PodmanTestIntegration {
|
||||
return PodmanTestCreateUtil(tempDir, false)
|
||||
}
|
||||
|
||||
// RestoreArtifact puts the cached image into our test store
|
||||
func (p *PodmanTestIntegration) RestoreArtifact(image string) error {
|
||||
tarball := imageTarPath(image)
|
||||
|
||||
@@ -5,6 +5,7 @@ package integration
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
@@ -37,16 +38,21 @@ func setupConnectionsConf() {
|
||||
os.Setenv("PODMAN_CONNECTIONS_CONF", file)
|
||||
}
|
||||
|
||||
var systemConnectionListCmd = []string{"system", "connection", "ls", "--format", "{{.Name}} {{.URI}} {{.Identity}} {{.Default}} {{.ReadWrite}}"}
|
||||
var farmListCmd = []string{"farm", "ls", "--format", "{{.Name}} {{.Connections}} {{.Default}} {{.ReadWrite}}"}
|
||||
var (
|
||||
systemConnectionListCmd = []string{"system", "connection", "ls", "--format", "{{.Name}} {{.URI}} {{.Identity}} {{.Default}} {{.ReadWrite}}"}
|
||||
systemConnectionListTLSSpecialValueCmd = []string{"system", "connection", "ls", "--format", "tls"}
|
||||
systemConnectionListTLSCmd = []string{"system", "connection", "ls", "--format", "{{.Name}} {{.URI}} {{.TLSCA}} {{.Default}} {{.ReadWrite}}"}
|
||||
systemConnectionListmTLSCmd = []string{"system", "connection", "ls", "--format", "{{.Name}} {{.URI}} {{.TLSCA}} {{.TLSCert}} {{.TLSKey}} {{.Default}} {{.ReadWrite}}"}
|
||||
farmListCmd = []string{"farm", "ls", "--format", "{{.Name}} {{.Connections}} {{.Default}} {{.ReadWrite}}"}
|
||||
)
|
||||
|
||||
var _ = Describe("podman system connection", func() {
|
||||
|
||||
BeforeEach(setupConnectionsConf)
|
||||
|
||||
Context("without running API service", func() {
|
||||
It("add ssh://", func() {
|
||||
cmd := []string{"system", "connection", "add",
|
||||
cmd := []string{
|
||||
"system", "connection", "add",
|
||||
"--default",
|
||||
"--identity", "~/.ssh/id_rsa",
|
||||
"QA",
|
||||
@@ -62,7 +68,8 @@ var _ = Describe("podman system connection", func() {
|
||||
Expect(session).Should(ExitCleanly())
|
||||
Expect(session.OutputToString()).To(Equal("QA ssh://root@podman.test:2222/run/podman/podman.sock ~/.ssh/id_rsa true true"))
|
||||
|
||||
cmd = []string{"system", "connection", "rename",
|
||||
cmd = []string{
|
||||
"system", "connection", "rename",
|
||||
"QA",
|
||||
"QE",
|
||||
}
|
||||
@@ -77,7 +84,8 @@ var _ = Describe("podman system connection", func() {
|
||||
})
|
||||
|
||||
It("add UDS", func() {
|
||||
cmd := []string{"system", "connection", "add",
|
||||
cmd := []string{
|
||||
"system", "connection", "add",
|
||||
"QA-UDS",
|
||||
"unix:///run/podman/podman.sock",
|
||||
}
|
||||
@@ -93,7 +101,8 @@ var _ = Describe("podman system connection", func() {
|
||||
Expect(session).Should(ExitCleanly())
|
||||
Expect(session.OutputToString()).To(Equal("QA-UDS unix:///run/podman/podman.sock true true"))
|
||||
|
||||
cmd = []string{"system", "connection", "add",
|
||||
cmd = []string{
|
||||
"system", "connection", "add",
|
||||
"QA-UDS1",
|
||||
"--socket-path", "/run/user/podman/podman.sock",
|
||||
"unix:///run/podman/podman.sock",
|
||||
@@ -112,7 +121,8 @@ QA-UDS1 unix:///run/user/podman/podman.sock false true
|
||||
})
|
||||
|
||||
It("add tcp", func() {
|
||||
cmd := []string{"system", "connection", "add",
|
||||
cmd := []string{
|
||||
"system", "connection", "add",
|
||||
"QA-TCP",
|
||||
"tcp://localhost:8888",
|
||||
}
|
||||
@@ -127,8 +137,52 @@ QA-UDS1 unix:///run/user/podman/podman.sock false true
|
||||
Expect(session.OutputToString()).To(Equal("QA-TCP tcp://localhost:8888 true true"))
|
||||
})
|
||||
|
||||
It("add tcp w/ TLS", func() {
|
||||
cmd := []string{
|
||||
"system", "connection", "add",
|
||||
"QA-TCP-TLS",
|
||||
"tcp://localhost:8888",
|
||||
"--tls-ca", "ca.pem",
|
||||
}
|
||||
session := podmanTest.Podman(cmd)
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
Expect(session.Out.Contents()).Should(BeEmpty())
|
||||
|
||||
session = podmanTest.Podman(systemConnectionListTLSCmd)
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
Expect(session.OutputToString()).To(Equal("QA-TCP-TLS tcp://localhost:8888 ca.pem true true"))
|
||||
})
|
||||
|
||||
It("add tcp w/ mTLS", func() {
|
||||
cmd := []string{
|
||||
"system", "connection", "add",
|
||||
"QA-TCP-MTLS",
|
||||
"tcp://localhost:8888",
|
||||
"--tls-ca", "ca.pem",
|
||||
"--tls-cert", "tls.crt",
|
||||
"--tls-key", "tls.key",
|
||||
}
|
||||
session := podmanTest.Podman(cmd)
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
Expect(session.Out.Contents()).Should(BeEmpty())
|
||||
|
||||
session = podmanTest.Podman(systemConnectionListmTLSCmd)
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
Expect(session.OutputToString()).To(Equal("QA-TCP-MTLS tcp://localhost:8888 ca.pem tls.crt tls.key true true"))
|
||||
|
||||
session = podmanTest.Podman(systemConnectionListTLSSpecialValueCmd)
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(ExitCleanly())
|
||||
Expect(session.Out).Should(Say("Name *URI *Identity *TLSCA *TLSCert *TLSKey *Default *ReadWrite\nQA-TCP-MTLS *tcp://localhost:8888 *ca.pem *tls.crt *tls.key *true *true"))
|
||||
})
|
||||
|
||||
It("add tcp to reverse proxy path", func() {
|
||||
cmd := []string{"system", "connection", "add",
|
||||
cmd := []string{
|
||||
"system", "connection", "add",
|
||||
"QA-TCP-RP",
|
||||
"tcp://localhost:8888/reverse/proxy/path/prefix",
|
||||
}
|
||||
@@ -144,7 +198,8 @@ QA-UDS1 unix:///run/user/podman/podman.sock false true
|
||||
})
|
||||
|
||||
It("add to new farm", func() {
|
||||
cmd := []string{"system", "connection", "add",
|
||||
cmd := []string{
|
||||
"system", "connection", "add",
|
||||
"--default",
|
||||
"--identity", "~/.ssh/id_rsa",
|
||||
"--farm", "farm1",
|
||||
@@ -174,7 +229,8 @@ QA-UDS1 unix:///run/user/podman/podman.sock false true
|
||||
Expect(session).Should(ExitCleanly())
|
||||
Expect(session.Out.Contents()).Should(ContainSubstring("Farm \"empty-farm\" created"))
|
||||
|
||||
cmd = []string{"system", "connection", "add",
|
||||
cmd = []string{
|
||||
"system", "connection", "add",
|
||||
"--default",
|
||||
"--identity", "~/.ssh/id_rsa",
|
||||
"--farm", "empty-farm",
|
||||
@@ -197,7 +253,8 @@ QA-UDS1 unix:///run/user/podman/podman.sock false true
|
||||
})
|
||||
|
||||
It("removing connection should remove from farm also", func() {
|
||||
cmd := []string{"system", "connection", "add",
|
||||
cmd := []string{
|
||||
"system", "connection", "add",
|
||||
"--default",
|
||||
"--identity", "~/.ssh/id_rsa",
|
||||
"--farm", "farm1",
|
||||
@@ -235,7 +292,8 @@ QA-UDS1 unix:///run/user/podman/podman.sock false true
|
||||
})
|
||||
|
||||
It("remove", func() {
|
||||
session := podmanTest.Podman([]string{"system", "connection", "add",
|
||||
session := podmanTest.Podman([]string{
|
||||
"system", "connection", "add",
|
||||
"--default",
|
||||
"--identity", "~/.ssh/id_rsa",
|
||||
"QA",
|
||||
@@ -259,7 +317,8 @@ QA-UDS1 unix:///run/user/podman/podman.sock false true
|
||||
})
|
||||
|
||||
It("remove --all", func() {
|
||||
session := podmanTest.Podman([]string{"system", "connection", "add",
|
||||
session := podmanTest.Podman([]string{
|
||||
"system", "connection", "add",
|
||||
"--default",
|
||||
"--identity", "~/.ssh/id_rsa",
|
||||
"QA",
|
||||
@@ -282,7 +341,8 @@ QA-UDS1 unix:///run/user/podman/podman.sock false true
|
||||
|
||||
It("default", func() {
|
||||
for _, name := range []string{"devl", "qe"} {
|
||||
cmd := []string{"system", "connection", "add",
|
||||
cmd := []string{
|
||||
"system", "connection", "add",
|
||||
"--default",
|
||||
"--identity", "~/.ssh/id_rsa",
|
||||
name,
|
||||
@@ -351,20 +411,39 @@ qe ssh://root@podman.test:2222/run/podman/podman.sock ~/.ssh/id_rsa false true
|
||||
proxy := http.NewServeMux()
|
||||
proxy.Handle(pathPrefix+"/", &httputil.ReverseProxy{
|
||||
Rewrite: func(pr *httputil.ProxyRequest) {
|
||||
defer GinkgoRecover()
|
||||
proxyGotUsed = true
|
||||
pr.Out.URL.Path = strings.TrimPrefix(pr.Out.URL.Path, pathPrefix)
|
||||
pr.Out.URL.RawPath = strings.TrimPrefix(pr.Out.URL.RawPath, pathPrefix)
|
||||
baseURL, _ := url.Parse("http://d")
|
||||
scheme := "http"
|
||||
if podmanTest.RemoteTLSServerCAFile != "" {
|
||||
scheme = "https"
|
||||
}
|
||||
baseURL, err := url.Parse(scheme + "://localhost")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
pr.SetURL(baseURL)
|
||||
},
|
||||
Transport: &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
defer GinkgoRecover()
|
||||
By("Proxying to " + podmanTest.RemoteSocket)
|
||||
url, err := url.Parse(podmanTest.RemoteSocket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return (&net.Dialer{}).DialContext(ctx, "unix", url.Path)
|
||||
switch podmanTest.RemoteSocketScheme {
|
||||
case "unix":
|
||||
return (&net.Dialer{}).DialContext(ctx, podmanTest.RemoteSocketScheme, url.Path)
|
||||
case "tcp":
|
||||
return (&net.Dialer{}).DialContext(ctx, podmanTest.RemoteSocketScheme, url.Host)
|
||||
default:
|
||||
Fail("Unexpected remote socket scheme")
|
||||
panic("")
|
||||
}
|
||||
},
|
||||
TLSClientConfig: &tls.Config{
|
||||
RootCAs: podmanTest.RemoteTLSServerCAPool,
|
||||
Certificates: podmanTest.RemoteTLSClientCerts,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -60,14 +60,18 @@ function setup() {
|
||||
if ! is_remote; then
|
||||
skip "only applicable on podman-remote"
|
||||
fi
|
||||
|
||||
# All we care about here is that the command passes
|
||||
run_podman --context=default version
|
||||
|
||||
# This one must fail
|
||||
PODMAN=${PODMAN%%--url*} run_podman 125 --context=swarm version
|
||||
is "$output" \
|
||||
"Error: read cli flags: connection \"swarm\" not found" \
|
||||
"--context=swarm should fail"
|
||||
(
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
# This one must fail
|
||||
PODMAN=${PODMAN%%--url*} run_podman 125 --context=swarm version
|
||||
is "$output" \
|
||||
"Error: read cli flags: connection \"swarm\" not found" \
|
||||
"--context=swarm should fail"
|
||||
)
|
||||
}
|
||||
|
||||
@test "podman can pull an image" {
|
||||
|
||||
@@ -434,7 +434,7 @@ EOF
|
||||
# that listing all images does not fail (see BZ 2216700).
|
||||
for i in $(seq --format '%02g' 1 $count); do
|
||||
timeout --foreground -v --kill=10 60 \
|
||||
$PODMAN rmi img-$i-$(safename) &
|
||||
"${PODMAN_CMD[@]}" rmi img-$i-$(safename) &
|
||||
done
|
||||
|
||||
tries=100
|
||||
|
||||
@@ -6,7 +6,7 @@ load helpers.sig-proxy
|
||||
# Each of the tests below does some setup, then invokes the helper from helpers.sig-proxy.bash.
|
||||
@test "podman sigproxy test: run" {
|
||||
# We're forced to use $PODMAN because run_podman cannot be backgrounded
|
||||
$PODMAN run -i --name c_run $IMAGE sh -c "$SLEEPLOOP" &
|
||||
"${PODMAN_CMD[@]}" run -i --name c_run $IMAGE sh -c "$SLEEPLOOP" &
|
||||
local kidpid=$!
|
||||
|
||||
_test_sigproxy c_run $kidpid
|
||||
@@ -16,7 +16,7 @@ load helpers.sig-proxy
|
||||
run_podman create --name c_start $IMAGE sh -c "$SLEEPLOOP"
|
||||
|
||||
# See above comments regarding $PODMAN and backgrounding
|
||||
$PODMAN start --attach c_start &
|
||||
"${PODMAN_CMD[@]}" start --attach c_start &
|
||||
local kidpid=$!
|
||||
|
||||
_test_sigproxy c_start $kidpid
|
||||
@@ -26,7 +26,7 @@ load helpers.sig-proxy
|
||||
run_podman run -d --name c_attach $IMAGE sh -c "$SLEEPLOOP"
|
||||
|
||||
# See above comments regarding $PODMAN and backgrounding
|
||||
$PODMAN attach c_attach &
|
||||
"${PODMAN_CMD[@]}" attach c_attach &
|
||||
local kidpid=$!
|
||||
|
||||
_test_sigproxy c_attach $kidpid
|
||||
|
||||
@@ -143,7 +143,7 @@ function _log_test_restarted() {
|
||||
run_podman run --log-driver=$driver ${events_backend} --name $cname $IMAGE sh -c 'start=0; if test -s log; then start=`tail -n 1 log`; fi; seq `expr $start + 1` `expr $start + 10` | tee -a log'
|
||||
run_podman ${events_backend} start -a $cname
|
||||
logfile=$(mktemp -p ${PODMAN_TMPDIR} logfileXXXXXXXX)
|
||||
$PODMAN $_PODMAN_TEST_OPTS ${events_backend} logs -f $cname > $logfile
|
||||
"${PODMAN_CMD[@]}" $_PODMAN_TEST_OPTS ${events_backend} logs -f $cname > $logfile
|
||||
expected=$(mktemp -p ${PODMAN_TMPDIR} expectedXXXXXXXX)
|
||||
seq 1 20 > $expected
|
||||
diff -u ${expected} ${logfile}
|
||||
|
||||
@@ -183,7 +183,7 @@ load helpers
|
||||
# Stop the container, but do so in the background so we can inspect
|
||||
# the container status while it's stopping. Use $PODMAN because we
|
||||
# don't want the overhead and error checks of run_podman.
|
||||
$PODMAN stop -t 20 $ctrname &
|
||||
"${PODMAN_CMD[@]}" stop -t 20 $ctrname &
|
||||
|
||||
# Wait for container to acknowledge the signal. We can't use wait_for_output
|
||||
# because that aborts if .State.Running != true
|
||||
|
||||
@@ -933,7 +933,7 @@ load helpers
|
||||
# that podman's stdout is redirected cleanly with no artifacts.
|
||||
|
||||
# Copy file.
|
||||
$PODMAN cp $cpcontainer:/tmp/file.txt - > $srcdir/stdout.tar
|
||||
"${PODMAN_CMD[@]}" cp $cpcontainer:/tmp/file.txt - > $srcdir/stdout.tar
|
||||
|
||||
tar xvf $srcdir/stdout.tar -C $srcdir
|
||||
is "$(< $srcdir/file.txt)" "$rand_content" "File contents: file.txt"
|
||||
@@ -943,7 +943,7 @@ load helpers
|
||||
rm -f $srcdir/*
|
||||
|
||||
# Copy directory.
|
||||
$PODMAN cp $cpcontainer:/tmp - > $srcdir/stdout.tar
|
||||
"${PODMAN_CMD[@]}" cp $cpcontainer:/tmp - > $srcdir/stdout.tar
|
||||
|
||||
tar xvf $srcdir/stdout.tar -C $srcdir
|
||||
is "$(< $srcdir/tmp/file.txt)" "$rand_content" "file.txt contents"
|
||||
|
||||
@@ -66,7 +66,7 @@ verify_iid_and_name() {
|
||||
# We can't use run_podman because that uses the BATS 'run' function
|
||||
# which redirects stdout and stderr. Here we need to guarantee
|
||||
# that podman's stdout is a pipe, not any other form of redirection
|
||||
$PODMAN save --format oci-archive $fqin | cat >$archive
|
||||
"${PODMAN_CMD[@]}" save --format oci-archive $fqin | cat >$archive
|
||||
assert "$?" -eq 0 "Command failed: podman save ... | cat"
|
||||
|
||||
# Make sure we can reload it
|
||||
@@ -129,7 +129,7 @@ verify_iid_and_name() {
|
||||
is "$output" "Copying blob .*Copying config.*Writing manifest"
|
||||
|
||||
# confirm that image was copied. FIXME: also try $PODMAN image inspect?
|
||||
_sudo $PODMAN image exists $newname
|
||||
_sudo "${PODMAN_CMD[@]}" image exists $newname
|
||||
|
||||
# Copy it back, this time using -q
|
||||
run_podman untag $IMAGE $newname
|
||||
@@ -150,16 +150,16 @@ verify_iid_and_name() {
|
||||
assert "$output" =~ "$src_digest" "Digest of re-fetched image is in list of original image digests"
|
||||
|
||||
# remove root img for transfer back with another name
|
||||
_sudo $PODMAN image rm $newname
|
||||
_sudo "${PODMAN_CMD[@]}" image rm $newname
|
||||
|
||||
# get foobar's ID, for an ID transfer test
|
||||
run_podman image inspect --format '{{.ID}}' foobar:123
|
||||
run_podman image scp $output ${notme}@localhost::foobartwo
|
||||
|
||||
_sudo $PODMAN image exists foobartwo
|
||||
_sudo "${PODMAN_CMD[@]}" image exists foobartwo
|
||||
|
||||
# Clean up
|
||||
_sudo $PODMAN image rm foobartwo
|
||||
_sudo "${PODMAN_CMD[@]}" image rm foobartwo
|
||||
run_podman untag $IMAGE $newname
|
||||
|
||||
# Negative test for nonexistent image.
|
||||
@@ -293,7 +293,7 @@ verify_iid_and_name() {
|
||||
# We can't use run_podman because that uses the BATS 'run' function
|
||||
# which redirects stdout and stderr. Here we need to guarantee
|
||||
# that podman's stdout is a pipe, not any other form of redirection
|
||||
$PODMAN save -m $img1 $img2 | cat >$archive
|
||||
"${PODMAN_CMD[@]}" save -m $img1 $img2 | cat >$archive
|
||||
assert "$?" -eq 0 "Command failed: podman save ... | cat"
|
||||
|
||||
run_podman rmi -f $img1 $img2
|
||||
|
||||
@@ -13,7 +13,7 @@ load helpers
|
||||
|
||||
# Start a container that will handle all signals by emitting 'got: N'
|
||||
local -a signals=(1 2 3 4 5 6 8 10 12 13 14 15 16 20 21 22 23 24 25 26 64)
|
||||
$PODMAN run --name $cname $IMAGE sh -c \
|
||||
"${PODMAN_CMD[@]}" run --name $cname $IMAGE sh -c \
|
||||
"for i in ${signals[*]}; do trap \"echo got: \$i\" \$i; done;
|
||||
echo READY;
|
||||
while ! test -e /stop; do sleep 0.1; done;
|
||||
@@ -121,7 +121,7 @@ load helpers
|
||||
# 14761 - concurrent kill/stop must record the exit code
|
||||
cname=c-$(safename)
|
||||
run_podman run -d --replace --name=$cname $IMAGE sh -c "trap 'echo Received SIGTERM, ignoring' SIGTERM; echo READY; while :; do sleep 0.2; done"
|
||||
$PODMAN stop -t 1 $cname &
|
||||
"${PODMAN_CMD[@]}" stop -t 1 $cname &
|
||||
run_podman kill $cname
|
||||
run_podman wait $cname
|
||||
run_podman rm -f $cname
|
||||
|
||||
@@ -275,7 +275,7 @@ EOF
|
||||
# The "-v" is only for debugging: tar will emit the filename to stderr.
|
||||
# If this test ever fails, that may give a clue.
|
||||
echo "$_LOG_PROMPT $PODMAN volume export $volname | tar -x ..."
|
||||
tar_output="$($PODMAN volume export $volname | tar -x -v --to-stdout)"
|
||||
tar_output="$("${PODMAN_CMD[@]}" volume export $volname | tar -x -v --to-stdout)"
|
||||
echo "$tar_output"
|
||||
assert "$tar_output" == "$content" "extracted content"
|
||||
|
||||
|
||||
@@ -589,7 +589,7 @@ io.max | $lomajmin rbps=1048576 wbps=1048576 riops=max wiops=max
|
||||
done
|
||||
|
||||
# and delete them
|
||||
$PODMAN pod rm -a &
|
||||
"${PODMAN_CMD[@]}" pod rm -a &
|
||||
|
||||
# pod ps should not fail while pods are deleted
|
||||
run_podman pod ps -q
|
||||
|
||||
@@ -174,7 +174,7 @@ Log[-1].Output | \"Uh-oh on stdout!\\\nUh-oh on stderr!\\\n\"
|
||||
|
||||
# Wait for the container in the background and create the $wait_file to
|
||||
# signal the specified wait condition was met.
|
||||
(timeout --foreground -v --kill=5 10 $PODMAN wait --condition=$condition $ctr && touch $wait_file) &
|
||||
(timeout --foreground -v --kill=5 10 "${PODMAN_CMD[@]}" wait --condition=$condition $ctr && touch $wait_file) &
|
||||
|
||||
# Sleep 1 second to make sure above commands are running
|
||||
sleep 1
|
||||
@@ -428,7 +428,7 @@ function _check_health_log {
|
||||
$IMAGE /home/podman/pause
|
||||
|
||||
timeout --foreground -v --kill=10 60 \
|
||||
$PODMAN healthcheck run $ctr &> $hcStatus &
|
||||
"${PODMAN_CMD[@]}" healthcheck run $ctr &> $hcStatus &
|
||||
hc_pid=$!
|
||||
|
||||
run_podman inspect $ctr --format "{{.State.Status}}"
|
||||
|
||||
@@ -15,7 +15,13 @@ function teardown() {
|
||||
basic_teardown
|
||||
}
|
||||
|
||||
function _podman_system_service {
|
||||
systemd-run --unit=$SERVICE_NAME ${PODMAN%%-remote} system service "$@"
|
||||
}
|
||||
|
||||
@test "podman system service <bad_scheme_uri> returns error" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
run_podman 125 system service localhost:9292
|
||||
is "$output" "Error: API Service endpoint scheme \"localhost\" is not supported. Try tcp://localhost:9292 or unix://localhost:9292"
|
||||
@@ -25,10 +31,12 @@ function teardown() {
|
||||
}
|
||||
|
||||
@test "podman system service unix: without two slashes still works" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
URL=unix:$PODMAN_TMPDIR/myunix.sock
|
||||
|
||||
systemd-run --unit=$SERVICE_NAME $PODMAN system service $URL --time=0
|
||||
_podman_system_service $URL --time=0
|
||||
wait_for_file $PODMAN_TMPDIR/myunix.sock
|
||||
|
||||
run_podman --host $URL info --format '{{.Host.RemoteSocket.Path}}'
|
||||
@@ -39,6 +47,8 @@ function teardown() {
|
||||
}
|
||||
|
||||
@test "podman-system-service containers survive service stop" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
local runtime=$(podman_runtime)
|
||||
if [[ "$runtime" != "crun" ]]; then
|
||||
@@ -48,7 +58,7 @@ function teardown() {
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
systemd-run --unit=$SERVICE_NAME $PODMAN system service $URL --time=0
|
||||
_podman_system_service $URL --time=0
|
||||
wait_for_port 127.0.0.1 $port
|
||||
|
||||
# Start a long-running container.
|
||||
@@ -69,16 +79,18 @@ function teardown() {
|
||||
# This doesn't actually test podman system service, but we require it,
|
||||
# so least-awful choice is to run from this test file.
|
||||
@test "podman --host / -H options" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
# %%-remote makes this run real podman even when testing podman-remote
|
||||
systemd-run --unit=$SERVICE_NAME ${PODMAN%%-remote*} system service $URL --time=0
|
||||
_podman_system_service $URL --time=0
|
||||
wait_for_port 127.0.0.1 $port
|
||||
|
||||
for opt in --host -H; do
|
||||
run_podman $opt $URL info --format '{{.Host.RemoteSocket.Path}}'
|
||||
is "$output" "$URL" "RemoteSocket.Path using $opt"
|
||||
run_podman $opt $URL info --format '{{.Host.RemoteSocket.Path}}'
|
||||
is "$output" "$URL" "RemoteSocket.Path using $opt"
|
||||
done
|
||||
|
||||
systemctl stop $SERVICE_NAME
|
||||
@@ -86,12 +98,14 @@ function teardown() {
|
||||
|
||||
# Regression test for https://github.com/containers/podman/issues/17749
|
||||
@test "podman-system-service --log-level=trace should be able to hijack" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
systemd-run --unit=$SERVICE_NAME $PODMAN --log-level=trace system service $URL --time=0
|
||||
_podman_system_service $URL --time=0
|
||||
wait_for_port 127.0.0.1 $port
|
||||
|
||||
out=o-$(random_string)
|
||||
@@ -102,3 +116,230 @@ function teardown() {
|
||||
run_podman --url $URL rm $cname
|
||||
systemctl stop $SERVICE_NAME
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-cert without --tls-key fails to start" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
run_podman 125 system service "tcp://localhost:${port}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}"
|
||||
is "$output" ".* --tls-cert provided without --tls-key"
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-key without --tls-cert fails to start" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
run_podman 125 system service "tcp://localhost:${port}" \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}"
|
||||
is "$output" ".* --tls-key provided without --tls-cert"
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-key=missing fails to start" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
run_podman 125 system service "tcp://localhost:${port}" --tls-key=no-such-file.pem --tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}"
|
||||
is "$output" ".* no-such-file.pem: no such file or directory"
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-cert=missing fails to start" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
run_podman 125 system service "tcp://localhost:${port}" --tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}" --tls-cert=no-such-file.pem
|
||||
is "$output" ".* no-such-file.pem: no such file or directory"
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-client-ca=missing fails to start" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
run_podman 125 system service "tcp://localhost:${port}" \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}" \
|
||||
--tls-client-ca=no-such-file.pem
|
||||
is "$output" ".* no-such-file.pem: no such file or directory"
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-key=malformed fails to start" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
echo 'not a cert' >"${PODMAN_TMPDIR}/not-a-cert.pem"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
run_podman 125 system service "${URL}" \
|
||||
--tls-key="${PODMAN_TMPDIR}/not-a-cert.pem" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}"
|
||||
is "$output" ".* failed to find any PEM data in key input"
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-cert=malformed fails to start" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
echo 'not a cert' >"${PODMAN_TMPDIR}/not-a-cert.pem"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
run_podman 125 system service "${URL}" \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}" \
|
||||
--tls-cert="${PODMAN_TMPDIR}/not-a-cert.pem"
|
||||
is "$output" ".* failed to find any PEM data in certificate input"
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-client-ca=malformed fails to start" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
echo 'not a cert' >"${PODMAN_TMPDIR}/not-a-cert.pem"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
run_podman 125 system service "${URL}" \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}" \
|
||||
--tls-client-ca="${PODMAN_TMPDIR}/not-a-cert.pem"
|
||||
is "$output" ".* ${PODMAN_TMPDIR}/not-a-cert.pem: non-PEM data found"
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-key=cert fails to start" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
run_podman 125 system service "${URL}" \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_CRT}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}"
|
||||
is "$output" ".*found a certificate rather than a key.*"
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-cert=key fails to start" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
run_podman 125 system service "${URL}" \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_KEY}"
|
||||
is "$output" ".* PEM inputs may have been switched"
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-client-ca=key fails to start" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
run_podman 125 system service "${URL}" \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}" \
|
||||
--tls-client-ca="${REMOTESYSTEM_TLS_CA_KEY}"
|
||||
is "$output" ".* ${REMOTESYSTEM_TLS_CA_KEY}: non-certificate type \`.*\` PEM data found"
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-cert --tls-key refuses HTTP client" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
_podman_system_service $URL --time=0 \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}" \
|
||||
--tls-client-ca="${REMOTESYSTEM_TLS_CA_CRT}"
|
||||
|
||||
wait_for_port 127.0.0.1 $port
|
||||
|
||||
run_podman 125 --url $URL system info
|
||||
is "$output" ".* ping response was 400"
|
||||
systemctl stop $SERVICE_NAME
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-cert --tls-key --tls-client-ca refuses client without cert" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
_podman_system_service $URL --time=0 \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}" \
|
||||
--tls-client-ca="${REMOTESYSTEM_TLS_CA_CRT}"
|
||||
|
||||
wait_for_port 127.0.0.1 $port
|
||||
|
||||
run_podman 125 --url $URL --tls-ca="${REMOTESYSTEM_TLS_CA_CRT}" system info
|
||||
is "$output" ".* remote error: tls: certificate required"
|
||||
systemctl stop $SERVICE_NAME
|
||||
}
|
||||
|
||||
@test "podman-system-service --tls-cert --tls-key --tls-client-ca refuses client untrusted cert" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
skip_if_remote "podman system service unavailable over remote"
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
_podman_system_service $URL --time=0 \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}" \
|
||||
--tls-client-ca="${REMOTESYSTEM_TLS_CA_CRT}"
|
||||
|
||||
wait_for_port 127.0.0.1 $port
|
||||
|
||||
run_podman 125 \
|
||||
--url $URL \
|
||||
--tls-key="${REMOTESYSTEM_TLS_BOGUS_KEY}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_BOGUS_CRT}" \
|
||||
--tls-ca="${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
system info
|
||||
# This is not a copy-paste error from above, the Go HTTPS server provides the same error message for
|
||||
# "you didn't provide a cert"
|
||||
# and
|
||||
# "you didn't provide a cert *that I trust*"
|
||||
# This is allegedly to make it "more secure"
|
||||
is "$output" ".* remote error: tls: certificate required"
|
||||
systemctl stop $SERVICE_NAME
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ SOCKET_FILE="$UNIT_DIR/$SERVICE_NAME.socket"
|
||||
PORT=$(random_free_port)
|
||||
|
||||
log=${PODMAN_TMPDIR}/system-service.log
|
||||
$PODMAN system service --cors="*" tcp:$SERVICE_TCP_HOST:$PORT -t 20 2> $log &
|
||||
"${PODMAN_CMD[@]}" system service --cors="*" tcp:$SERVICE_TCP_HOST:$PORT -t 20 2> $log &
|
||||
podman_pid="$!"
|
||||
|
||||
wait_for_port $SERVICE_TCP_HOST $PORT
|
||||
@@ -42,7 +42,7 @@ SOCKET_FILE="$UNIT_DIR/$SERVICE_NAME.socket"
|
||||
@test "podman system service - tcp without CORS" {
|
||||
skip_if_remote "system service tests are meaningless over remote"
|
||||
PORT=$(random_free_port)
|
||||
$PODMAN system service tcp:$SERVICE_TCP_HOST:$PORT -t 20 &
|
||||
"${PODMAN_CMD[@]}" system service tcp:$SERVICE_TCP_HOST:$PORT -t 20 &
|
||||
podman_pid="$!"
|
||||
|
||||
wait_for_port $SERVICE_TCP_HOST $PORT
|
||||
@@ -65,7 +65,7 @@ SOCKET_FILE="$UNIT_DIR/$SERVICE_NAME.socket"
|
||||
PORT=$(random_free_port)
|
||||
run_podman 0+w system service --log-level="debug" --cors="*" -t 1 tcp:$SERVICE_TCP_HOST:$PORT
|
||||
is "$output" ".*CORS Headers were set to ..\*...*" "debug log confirms CORS headers set"
|
||||
assert "$output" =~ "level=warning msg=\"Using the Podman API service with TCP sockets is not recommended" \
|
||||
assert "$output" =~ "level=warning msg=\"Using the Podman API service with TCP sockets without TLS is not recommended" \
|
||||
"TCP socket warning"
|
||||
}
|
||||
|
||||
|
||||
@@ -44,15 +44,21 @@ function teardown() {
|
||||
#
|
||||
# Needed because, in CI, PODMAN="/path/to/podman-remote --url /path/to/socket"
|
||||
# which of course overrides podman's detection and use of a connection.
|
||||
function _run_podman_remote() {
|
||||
function run_podman_remote() {
|
||||
PODMAN=${PODMAN%%--url*} run_podman "$@"
|
||||
}
|
||||
|
||||
# Very basic test, does not actually connect at any time
|
||||
@test "podman system connection - basic add / ls / remove" {
|
||||
unset REMOTESYSTEM_TRANSPORT REMOTESYSTEM_TLS_{CLIENT,SERVER,CA}_{CRT,KEY}
|
||||
|
||||
run_podman system connection ls
|
||||
is "$output" "Name URI Identity Default ReadWrite" \
|
||||
"system connection ls: no connections"
|
||||
run_podman system connection ls --format=tls
|
||||
is "$output" "Name URI Identity TLSCA TLSCert TLSKey Default ReadWrite" \
|
||||
"system connection ls: no connections"
|
||||
|
||||
|
||||
c1="c1_$(random_string 15)"
|
||||
c2="c2_$(random_string 15)"
|
||||
@@ -90,6 +96,8 @@ $c2[ ]\+tcp://localhost:54321[ ]\+true[ ]\+true" \
|
||||
|
||||
# Test tcp socket; requires starting a local server
|
||||
@test "podman system connection - tcp" {
|
||||
unset REMOTESYSTEM_TRANSPORT REMOTESYSTEM_TLS_{CLIENT,SERVER,CA}_{CRT,KEY}
|
||||
|
||||
# Start server
|
||||
_SERVICE_PORT=$(random_free_port 63000-64999)
|
||||
|
||||
@@ -100,7 +108,7 @@ $c2[ ]\+tcp://localhost:54321[ ]\+true[ ]\+true" \
|
||||
# to "podman-remote --url sdfsdf". This of course overrides the default
|
||||
# podman-remote action. Our solution: strip off the "--url xyz" part
|
||||
# when invoking podman.
|
||||
_run_podman_remote 125 info
|
||||
run_podman_remote 125 info
|
||||
is "$output" \
|
||||
"OS: .*provider:.*Cannot connect to Podman. Please verify.*dial tcp.*connection refused" \
|
||||
"podman info, without active service"
|
||||
@@ -115,7 +123,7 @@ $c2[ ]\+tcp://localhost:54321[ ]\+true[ ]\+true" \
|
||||
wait_for_port 127.0.0.1 $_SERVICE_PORT
|
||||
local timeout=10
|
||||
while [[ $timeout -gt 1 ]]; do
|
||||
_run_podman_remote '?' info --format '{{.Host.RemoteSocket.Path}}'
|
||||
run_podman_remote '?' info --format '{{.Host.RemoteSocket.Path}}'
|
||||
if [[ $status == 0 ]]; then
|
||||
break
|
||||
fi
|
||||
@@ -125,13 +133,139 @@ $c2[ ]\+tcp://localhost:54321[ ]\+true[ ]\+true" \
|
||||
is "$output" "tcp://localhost:$_SERVICE_PORT" \
|
||||
"podman info works, and talks to the correct server"
|
||||
|
||||
_run_podman_remote info --format '{{.Store.GraphRoot}}'
|
||||
run_podman_remote info --format '{{.Store.GraphRoot}}'
|
||||
is "$output" "${PODMAN_TMPDIR}/root" \
|
||||
"podman info, talks to the right service"
|
||||
|
||||
# Add another connection; make sure it does not get set as default
|
||||
_run_podman_remote system connection add fakeconnect tcp://localhost:$(( _SERVICE_PORT + 1))
|
||||
_run_podman_remote info --format '{{.Store.GraphRoot}}'
|
||||
run_podman_remote system connection add fakeconnect tcp://localhost:$(( _SERVICE_PORT + 1))
|
||||
run_podman_remote info --format '{{.Store.GraphRoot}}'
|
||||
# (Don't bother checking output; we just care about exit status)
|
||||
|
||||
# Stop server. Use 'run' to avoid failing on nonzero exit status
|
||||
run kill $_SERVICE_PID
|
||||
run wait $_SERVICE_PID
|
||||
_SERVICE_PID=
|
||||
|
||||
run_podman system connection rm fakeconnect
|
||||
run_podman system connection rm myconnect
|
||||
}
|
||||
|
||||
# Test tcp socket with server authentication; requires starting a local server
|
||||
@test "podman system connection - tls" {
|
||||
unset REMOTESYSTEM_TRANSPORT REMOTESYSTEM_TLS_{CLIENT,SERVER,CA}_{CRT,KEY}
|
||||
|
||||
# Start server
|
||||
_SERVICE_PORT=$(random_free_port 63000-64999)
|
||||
|
||||
# Add the connection, and run podman info *before* starting the service.
|
||||
# This should fail.
|
||||
run_podman system connection add myconnect tcp://localhost:$_SERVICE_PORT \
|
||||
--tls-ca="${REMOTESYSTEM_TLS_CA_CRT}"
|
||||
# IMPORTANT NOTE: in CI, podman-remote is tested by setting PODMAN
|
||||
# to "podman-remote --url sdfsdf". This of course overrides the default
|
||||
# podman-remote action. Our solution: strip off the "--url xyz" part
|
||||
# when invoking podman.
|
||||
run_podman_remote 125 info
|
||||
is "$output" \
|
||||
"OS: .*provider:.*Cannot connect to Podman. Please verify.*dial tcp.*connection refused" \
|
||||
"podman info, without active service"
|
||||
|
||||
# Start service. Now podman info should work fine. The %%-remote*
|
||||
# converts "podman-remote --opts" to just "podman", which is what
|
||||
# we need for the server.
|
||||
${PODMAN%%-remote*} $(podman_isolation_opts ${PODMAN_TMPDIR}) \
|
||||
system service -t 99 \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}" \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}" \
|
||||
tcp://localhost:$_SERVICE_PORT &
|
||||
_SERVICE_PID=$!
|
||||
# Wait for the port and the podman-service to be ready.
|
||||
wait_for_port 127.0.0.1 $_SERVICE_PORT
|
||||
local timeout=10
|
||||
while [[ $timeout -gt 1 ]]; do
|
||||
run_podman_remote '?' info --format '{{.Host.RemoteSocket.Path}}'
|
||||
if [[ $status == 0 ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
let timeout=$timeout-1
|
||||
done
|
||||
is "$output" "tcp://localhost:$_SERVICE_PORT" \
|
||||
"podman info works, and talks to the correct server"
|
||||
|
||||
run_podman_remote info --format '{{.Store.GraphRoot}}'
|
||||
is "$output" "${PODMAN_TMPDIR}/root" \
|
||||
"podman info, talks to the right service"
|
||||
|
||||
# Add another connection; make sure it does not get set as default
|
||||
run_podman_remote system connection add fakeconnect tcp://localhost:$(( _SERVICE_PORT + 1))
|
||||
run_podman_remote info --format '{{.Store.GraphRoot}}'
|
||||
# (Don't bother checking output; we just care about exit status)
|
||||
|
||||
# Stop server. Use 'run' to avoid failing on nonzero exit status
|
||||
run kill $_SERVICE_PID
|
||||
run wait $_SERVICE_PID
|
||||
_SERVICE_PID=
|
||||
|
||||
run_podman system connection rm fakeconnect
|
||||
run_podman system connection rm myconnect
|
||||
}
|
||||
|
||||
# Test tcp socket with mutual authentication; requires starting a local server
|
||||
@test "podman system connection - mtls" {
|
||||
unset REMOTESYSTEM_TRANSPORT REMOTESYSTEM_TLS_{CLIENT,SERVER,CA}_{CRT,KEY}
|
||||
|
||||
# Start server
|
||||
_SERVICE_PORT=$(random_free_port 63000-64999)
|
||||
|
||||
# Add the connection, and run podman info *before* starting the service.
|
||||
# This should fail.
|
||||
run_podman system connection add myconnect tcp://localhost:$_SERVICE_PORT \
|
||||
--tls-ca="${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_CLIENT_CRT}" \
|
||||
--tls-key="${REMOTESYSTEM_TLS_CLIENT_KEY}"
|
||||
|
||||
# IMPORTANT NOTE: in CI, podman-remote is tested by setting PODMAN
|
||||
# to "podman-remote --url sdfsdf". This of course overrides the default
|
||||
# podman-remote action. Our solution: strip off the "--url xyz" part
|
||||
# when invoking podman.
|
||||
run_podman_remote 125 info
|
||||
is "$output" \
|
||||
"OS: .*provider:.*Cannot connect to Podman. Please verify.*dial tcp.*connection refused" \
|
||||
"podman info, without active service"
|
||||
|
||||
# Start service. Now podman info should work fine. The %%-remote*
|
||||
# converts "podman-remote --opts" to just "podman", which is what
|
||||
# we need for the server.
|
||||
${PODMAN%%-remote*} $(podman_isolation_opts ${PODMAN_TMPDIR}) \
|
||||
system service -t 99 \
|
||||
--tls-client-ca="${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}" \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}" \
|
||||
tcp://localhost:$_SERVICE_PORT &
|
||||
_SERVICE_PID=$!
|
||||
# Wait for the port and the podman-service to be ready.
|
||||
wait_for_port 127.0.0.1 $_SERVICE_PORT
|
||||
local timeout=10
|
||||
while [[ $timeout -gt 1 ]]; do
|
||||
run_podman_remote '?' info --format '{{.Host.RemoteSocket.Path}}'
|
||||
if [[ $status == 0 ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
let timeout=$timeout-1
|
||||
done
|
||||
is "$output" "tcp://localhost:$_SERVICE_PORT" \
|
||||
"podman info works, and talks to the correct server"
|
||||
|
||||
run_podman_remote info --format '{{.Store.GraphRoot}}'
|
||||
is "$output" "${PODMAN_TMPDIR}/root" \
|
||||
"podman info, talks to the right service"
|
||||
|
||||
# Add another connection; make sure it does not get set as default
|
||||
run_podman_remote system connection add fakeconnect tcp://localhost:$(( _SERVICE_PORT + 1))
|
||||
run_podman_remote info --format '{{.Store.GraphRoot}}'
|
||||
# (Don't bother checking output; we just care about exit status)
|
||||
|
||||
# Stop server. Use 'run' to avoid failing on nonzero exit status
|
||||
@@ -145,6 +279,8 @@ $c2[ ]\+tcp://localhost:54321[ ]\+true[ ]\+true" \
|
||||
|
||||
# If we have ssh access to localhost (unlikely in CI), test that.
|
||||
@test "podman system connection - ssh" {
|
||||
unset REMOTESYSTEM_TRANSPORT REMOTESYSTEM_TLS_{CLIENT,SERVER,CA}_{CRT,KEY}
|
||||
|
||||
# system connection only really works if we have an agent
|
||||
run ssh-add -l
|
||||
test "$status" -eq 0 || skip "Not running under ssh-agent"
|
||||
@@ -172,7 +308,7 @@ $c2[ ]\+tcp://localhost:54321[ ]\+true[ ]\+true" \
|
||||
is "$output" "" "output from system connection add"
|
||||
|
||||
# debug logs will confirm that we use ssh connection
|
||||
_run_podman_remote --log-level=debug info --format '{{.Host.RemoteSocket.Path}}'
|
||||
run_podman_remote --log-level=debug info --format '{{.Host.RemoteSocket.Path}}'
|
||||
is "$output" ".*msg=\"SSH Agent Key .*" "we are truly using ssh"
|
||||
|
||||
# Clean up
|
||||
@@ -180,86 +316,99 @@ $c2[ ]\+tcp://localhost:54321[ ]\+true[ ]\+true" \
|
||||
}
|
||||
|
||||
@test "podman-remote: non-default connection" {
|
||||
|
||||
# priority:
|
||||
# 1. cli flags (--connection ,--url ,--context ,--host)
|
||||
# 2. Env variables (CONTAINER_HOST and CONTAINER_CONNECTION)
|
||||
# 3. ActiveService from containers.conf
|
||||
# 4. RemoteURI
|
||||
|
||||
# Prerequisite check: there must be no defined system connections
|
||||
run_podman system connection ls -q
|
||||
assert "$output" = "" "This test requires an empty list of system connections"
|
||||
(
|
||||
unset REMOTESYSTEM_TRANSPORT REMOTESYSTEM_TLS_{CLIENT,SERVER,CA}_{CRT,KEY}
|
||||
|
||||
# setup
|
||||
run_podman 0+w system connection add defaultconnection unix:///run/user/defaultconnection/podman/podman.sock
|
||||
run_podman 0+w system connection add env-override unix:///run/user/env-override/podman/podman.sock
|
||||
run_podman 0+w system connection add cli-override unix:///run/user/cli-override/podman/podman.sock
|
||||
# Prerequisite check: there must be no defined system connections
|
||||
run_podman system connection ls -q
|
||||
assert "$output" = "" "This test requires an empty list of system connections"
|
||||
|
||||
# Test priority of Env variables wrt cli flags
|
||||
CONTAINER_CONNECTION=env-override _run_podman_remote 125 --connection=cli-override ps
|
||||
assert "$output" =~ "/run/user/cli-override/podman/podman.sock" "test env variable CONTAINER_CONNECTION wrt --connection cli flag"
|
||||
# setup
|
||||
run_podman 0+w system connection add defaultconnection unix:///run/user/defaultconnection/podman/podman.sock
|
||||
run_podman 0+w system connection add env-override unix:///run/user/env-override/podman/podman.sock
|
||||
run_podman 0+w system connection add cli-override unix:///run/user/cli-override/podman/podman.sock
|
||||
|
||||
CONTAINER_HOST=foo://124.com _run_podman_remote 125 --connection=cli-override ps
|
||||
assert "$output" =~ "/run/user/cli-override/podman/podman.sock" "test env variable CONTAINER_HOST wrt --connection cli flag"
|
||||
# Test priority of Env variables wrt cli flags
|
||||
CONTAINER_CONNECTION=env-override run_podman_remote 125 --connection=cli-override ps
|
||||
assert "$output" =~ "/run/user/cli-override/podman/podman.sock" "test env variable CONTAINER_CONNECTION wrt --connection cli flag"
|
||||
|
||||
CONTAINER_CONNECTION=env-override _run_podman_remote 125 --url=tcp://localhost ps
|
||||
assert "$output" =~ "localhost" "test env variable CONTAINER_CONNECTION wrt --url cli flag"
|
||||
CONTAINER_HOST=foo://124.com run_podman_remote 125 --connection=cli-override ps
|
||||
assert "$output" =~ "/run/user/cli-override/podman/podman.sock" "test env variable CONTAINER_HOST wrt --connection cli flag"
|
||||
|
||||
CONTAINER_HOST=foo://124.com _run_podman_remote 125 --url=tcp://localhost ps
|
||||
assert "$output" =~ "localhost" "test env variable CONTAINER_HOST wrt --url cli flag"
|
||||
CONTAINER_CONNECTION=env-override run_podman_remote 125 --url=tcp://localhost ps
|
||||
assert "$output" =~ "localhost" "test env variable CONTAINER_CONNECTION wrt --url cli flag"
|
||||
|
||||
# Docker-compat
|
||||
CONTAINER_CONNECTION=env-override _run_podman_remote 125 --context=cli-override ps
|
||||
assert "$output" =~ "/run/user/cli-override/podman/podman.sock" "test env variable CONTAINER_CONNECTION wrt --context cli flag"
|
||||
CONTAINER_HOST=foo://124.com run_podman_remote 125 --url=tcp://localhost ps
|
||||
assert "$output" =~ "localhost" "test env variable CONTAINER_HOST wrt --url cli flag"
|
||||
|
||||
CONTAINER_HOST=foo://124.com _run_podman_remote 125 --context=cli-override ps
|
||||
assert "$output" =~ "/run/user/cli-override/podman/podman.sock" "test env variable CONTAINER_HOST wrt --context cli flag"
|
||||
# Docker-compat
|
||||
CONTAINER_CONNECTION=env-override run_podman_remote 125 --context=cli-override ps
|
||||
assert "$output" =~ "/run/user/cli-override/podman/podman.sock" "test env variable CONTAINER_CONNECTION wrt --context cli flag"
|
||||
|
||||
CONTAINER_CONNECTION=env-override _run_podman_remote 125 --host=tcp://localhost ps
|
||||
assert "$output" =~ "localhost" "test env variable CONTAINER_CONNECTION wrt --host cli flag"
|
||||
CONTAINER_HOST=foo://124.com run_podman_remote 125 --context=cli-override ps
|
||||
assert "$output" =~ "/run/user/cli-override/podman/podman.sock" "test env variable CONTAINER_HOST wrt --context cli flag"
|
||||
|
||||
CONTAINER_HOST=foo://124.com _run_podman_remote 125 --host=tcp://localhost ps
|
||||
assert "$output" =~ "localhost" "test env variable CONTAINER_HOST wrt --host cli flag"
|
||||
CONTAINER_CONNECTION=env-override run_podman_remote 125 --host=tcp://localhost ps
|
||||
assert "$output" =~ "localhost" "test env variable CONTAINER_CONNECTION wrt --host cli flag"
|
||||
|
||||
_run_podman_remote 125 --remote ps
|
||||
assert "$output" =~ "/run/user/defaultconnection/podman/podman.sock" "test default connection"
|
||||
CONTAINER_HOST=foo://124.com run_podman_remote 125 --host=tcp://localhost ps
|
||||
assert "$output" =~ "localhost" "test env variable CONTAINER_HOST wrt --host cli flag"
|
||||
|
||||
CONTAINER_CONNECTION=env-override _run_podman_remote 125 --remote ps
|
||||
assert "$output" =~ "/run/user/env-override/podman/podman.sock" "test env variable CONTAINER_CONNECTION wrt config"
|
||||
run_podman_remote 125 --remote ps
|
||||
assert "$output" =~ "/run/user/defaultconnection/podman/podman.sock" "test default connection"
|
||||
|
||||
CONTAINER_HOST=foo://124.com _run_podman_remote 125 --remote ps
|
||||
assert "$output" =~ "foo" "test env variable CONTAINER_HOST wrt config"
|
||||
CONTAINER_CONNECTION=env-override run_podman_remote 125 --remote ps
|
||||
assert "$output" =~ "/run/user/env-override/podman/podman.sock" "test env variable CONTAINER_CONNECTION wrt config"
|
||||
|
||||
# There was a bug where this would panic instead of returning a proper error (#22997)
|
||||
CONTAINER_CONNECTION=invalid-env _run_podman_remote 125 --remote ps
|
||||
assert "$output" =~ "read cli flags: connection \"invalid-env\" not found" "connection error from env"
|
||||
CONTAINER_HOST=foo://124.com run_podman_remote 125 --remote ps
|
||||
assert "$output" =~ "foo" "test env variable CONTAINER_HOST wrt config"
|
||||
|
||||
# Check again with cli overwrite to ensure correct connection name in error is reported
|
||||
CONTAINER_CONNECTION=invalid-env _run_podman_remote 125 --connection=invalid-cli ps
|
||||
assert "$output" =~ "read cli flags: connection \"invalid-cli\" not found" "connection error from --connection cli"
|
||||
# There was a bug where this would panic instead of returning a proper error (#22997)
|
||||
CONTAINER_CONNECTION=invalid-env run_podman_remote 125 --remote ps
|
||||
assert "$output" =~ "read cli flags: connection \"invalid-env\" not found" "connection error from env"
|
||||
|
||||
# Invalid env is fine if valid connection is given via cli
|
||||
CONTAINER_CONNECTION=invalid-env _run_podman_remote 125 --connection=cli-override ps
|
||||
assert "$output" =~ "/run/user/cli-override/podman/podman.sock" "no CONTAINER_CONNECTION connection error with valid --connection cli"
|
||||
# Check again with cli overwrite to ensure correct connection name in error is reported
|
||||
CONTAINER_CONNECTION=invalid-env run_podman_remote 125 --connection=invalid-cli ps
|
||||
assert "$output" =~ "read cli flags: connection \"invalid-cli\" not found" "connection error from --connection cli"
|
||||
|
||||
# Clean up
|
||||
run_podman system connection rm defaultconnection
|
||||
run_podman system connection rm env-override
|
||||
run_podman system connection rm cli-override
|
||||
# Invalid env is fine if valid connection is given via cli
|
||||
CONTAINER_CONNECTION=invalid-env run_podman_remote 125 --connection=cli-override ps
|
||||
assert "$output" =~ "/run/user/cli-override/podman/podman.sock" "no CONTAINER_CONNECTION connection error with valid --connection cli"
|
||||
|
||||
# Clean up
|
||||
run_podman system connection rm defaultconnection
|
||||
run_podman system connection rm env-override
|
||||
run_podman system connection rm cli-override
|
||||
)
|
||||
|
||||
# With all system connections removed, test the default connection.
|
||||
# This only works in upstream CI, where we run with a nonstandard socket.
|
||||
# In gating we use the default /run/...
|
||||
run_podman info --format '{{.Host.RemoteSocket.Path}}'
|
||||
local sock="$output"
|
||||
if [[ "$sock" =~ //run/ ]]; then
|
||||
_run_podman_remote --remote info --format '{{.Host.RemoteSocket.Path}}'
|
||||
assert "$output" = "$sock" "podman-remote is using default socket path"
|
||||
if [[ "${REMOTESYSTEM_TRANSPORT}" =~ tcp|tls|mtls ]]; then
|
||||
run_podman_remote --remote info --format '{{.Host.RemoteSocket.Path}}'
|
||||
assert "$output" =~ "tcp://localhost:${REMOTESYSTEM_TCP_PORT}"
|
||||
elif [[ "${REMOTESYSTEM_TRANSPORT}" =~ unix ]]; then
|
||||
run_podman_remote --remote info --format '{{.Host.RemoteSocket.Path}}'
|
||||
assert "$output" =~ "unix://${REMOTESYSTEM_UNIX_SOCK}"
|
||||
else
|
||||
# Nonstandard socket
|
||||
_run_podman_remote 125 --remote ps
|
||||
assert "$output" =~ "/run/[a-z0-9/]*podman/podman.sock"\
|
||||
"test absence of default connection"
|
||||
# This only works in upstream CI, where we run with a nonstandard socket.
|
||||
# In gating we use the default /run/...
|
||||
run_podman info --format '{{.Host.RemoteSocket.Path}}'
|
||||
local sock="$output"
|
||||
if [[ "$sock" =~ //run/ ]]; then
|
||||
run_podman_remote --remote info --format '{{.Host.RemoteSocket.Path}}'
|
||||
assert "$output" = "$sock" "podman-remote is using default socket path"
|
||||
else
|
||||
# Nonstandard socket
|
||||
run_podman_remote 125 --remote ps
|
||||
assert "$output" =~ "/run/[a-z0-9/]*podman/podman.sock"\
|
||||
"test absence of default connection"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
150
test/system/273-remote-spot-check.bats
Normal file
150
test/system/273-remote-spot-check.bats
Normal file
@@ -0,0 +1,150 @@
|
||||
#
|
||||
# Tests that spot check connectivity for each of the supported remote transports,
|
||||
# unix, tcp, tls, mtls
|
||||
|
||||
load helpers
|
||||
load helpers.systemd
|
||||
load helpers.network
|
||||
|
||||
SERVICE_NAME="podman-service-$(random_string)"
|
||||
|
||||
function setup() {
|
||||
basic_setup
|
||||
}
|
||||
|
||||
function teardown() {
|
||||
# Ignore exit status: this is just a backup stop in case tests failed
|
||||
run systemctl-user stop "$SERVICE_NAME"
|
||||
rm -f $PODMAN_TMPDIR/myunix.sock
|
||||
|
||||
basic_teardown
|
||||
}
|
||||
|
||||
@test "unix remote" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
URL=unix:$PODMAN_TMPDIR/myunix.sock
|
||||
|
||||
systemd-run-user --unit=$SERVICE_NAME ${PODMAN%%-remote*} system service $URL --time=0
|
||||
wait_for_file $PODMAN_TMPDIR/myunix.sock
|
||||
|
||||
# Variable works
|
||||
CONTAINER_HOST=$URL \
|
||||
run_podman \
|
||||
info --format '{{.Host.RemoteSocket.Path}}'
|
||||
is "$output" "$URL" "RemoteSocket.Path using unix:"
|
||||
# Flag works
|
||||
run_podman \
|
||||
--url="$URL" \
|
||||
info --format '{{.Host.RemoteSocket.Path}}'
|
||||
is "$output" "$URL" "RemoteSocket.Path using unix:"
|
||||
# Streaming command works
|
||||
run_podman \
|
||||
--url="$URL" \
|
||||
run --rm -i $IMAGE /bin/sh -c 'echo -n foo; sleep 0.1; echo -n bar; sleep 0.1; echo -n baz'
|
||||
is "$output" foobarbaz
|
||||
|
||||
systemctl-user stop $SERVICE_NAME
|
||||
rm -f $PODMAN_TMPDIR/myunix.sock
|
||||
}
|
||||
|
||||
@test "tcp remote" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
systemd-run-user --unit=$SERVICE_NAME ${PODMAN%%-remote*} system service $URL --time=0
|
||||
wait_for_port 127.0.0.1 $port
|
||||
|
||||
# Variable works
|
||||
CONTAINER_HOST=$URL \
|
||||
run_podman \
|
||||
info --format '{{.Host.RemoteSocket.Path}}'
|
||||
is "$output" "$URL" "RemoteSocket.Path using unix:"
|
||||
# Flag works
|
||||
run_podman \
|
||||
--url="$URL" \
|
||||
info --format '{{.Host.RemoteSocket.Path}}'
|
||||
is "$output" "$URL" "RemoteSocket.Path using unix:"
|
||||
# Streaming command works
|
||||
run_podman \
|
||||
--url="$URL" \
|
||||
run --rm -i $IMAGE /bin/sh -c 'echo -n foo; sleep 0.1; echo -n bar; sleep 0.1; echo -n baz'
|
||||
is "$output" foobarbaz
|
||||
|
||||
systemctl-user stop $SERVICE_NAME
|
||||
}
|
||||
|
||||
@test "tls remote" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
systemd-run-user --unit=$SERVICE_NAME ${PODMAN%%-remote*} system service $URL --time=0 \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}"
|
||||
wait_for_port 127.0.0.1 $port
|
||||
|
||||
# Variable works
|
||||
CONTAINER_HOST=$URL \
|
||||
run_podman \
|
||||
--tls-ca="${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
info --format '{{.Host.RemoteSocket.Path}}'
|
||||
is "$output" "$URL" "RemoteSocket.Path using unix:"
|
||||
# Flag works
|
||||
run_podman \
|
||||
--url="$URL" \
|
||||
--tls-ca="${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
info --format '{{.Host.RemoteSocket.Path}}'
|
||||
is "$output" "$URL" "RemoteSocket.Path using unix:"
|
||||
# Streaming command works
|
||||
run_podman \
|
||||
--url="$URL" \
|
||||
--tls-ca="${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
run --rm -i $IMAGE /bin/sh -c 'echo -n foo; sleep 0.1; echo -n bar; sleep 0.1; echo -n baz'
|
||||
is "$output" foobarbaz
|
||||
|
||||
systemctl-user stop $SERVICE_NAME
|
||||
}
|
||||
|
||||
@test "mtls remote" {
|
||||
unset REMOTESYSTEM_TRANSPORT
|
||||
|
||||
port=$(random_free_port)
|
||||
URL=tcp://127.0.0.1:$port
|
||||
|
||||
systemd-run-user --unit=$SERVICE_NAME ${PODMAN%%-remote*} system service $URL --time=0 \
|
||||
--tls-client-ca="${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}"
|
||||
wait_for_port 127.0.0.1 $port
|
||||
|
||||
# Variable works
|
||||
CONTAINER_HOST=$URL \
|
||||
run_podman \
|
||||
--tls-key="${REMOTESYSTEM_TLS_CLIENT_KEY}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_CLIENT_CRT}" \
|
||||
--tls-ca="${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
info --format '{{.Host.RemoteSocket.Path}}'
|
||||
is "$output" "$URL" "RemoteSocket.Path using unix:"
|
||||
# Flag works
|
||||
run_podman \
|
||||
--url="$URL" \
|
||||
--tls-key="${REMOTESYSTEM_TLS_CLIENT_KEY}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_CLIENT_CRT}" \
|
||||
--tls-ca="${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
info --format '{{.Host.RemoteSocket.Path}}'
|
||||
is "$output" "$URL" "RemoteSocket.Path using unix:"
|
||||
# Streaming command works
|
||||
run_podman \
|
||||
--url="$URL" \
|
||||
--tls-key="${REMOTESYSTEM_TLS_CLIENT_KEY}" \
|
||||
--tls-cert="${REMOTESYSTEM_TLS_CLIENT_CRT}" \
|
||||
--tls-ca="${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
run --rm -i $IMAGE /bin/sh -c 'echo -n foo; sleep 0.1; echo -n bar; sleep 0.1; echo -n baz'
|
||||
is "$output" foobarbaz
|
||||
|
||||
systemctl-user stop $SERVICE_NAME
|
||||
}
|
||||
@@ -129,12 +129,12 @@ function teardown() {
|
||||
run_podman run --rm -v testVol:/data $IMAGE sh -c "echo data > /data/file.txt"
|
||||
|
||||
# Positive Case
|
||||
$PODMAN volume export testVol --output=/dev/null >$PODMAN_TEST_PTY ||
|
||||
"${PODMAN_CMD[@]}" volume export testVol --output=/dev/null >$PODMAN_TEST_PTY ||
|
||||
die "$PODMAN volume export testVol --output=/dev/null failed when connected to terminal."
|
||||
|
||||
# Negative Case
|
||||
local rc=0
|
||||
$PODMAN volume export testVol >$PODMAN_TEST_PTY 2>$PODMAN_TMPDIR/out || rc=$?
|
||||
"${PODMAN_CMD[@]}" volume export testVol >$PODMAN_TEST_PTY 2>$PODMAN_TMPDIR/out || rc=$?
|
||||
|
||||
is "$rc" "125" "Exit code should be 125"
|
||||
is "$(<$PODMAN_TMPDIR/out)" "Error: cannot write to terminal, use command-line redirection or the --output flag" "Should refuse to export to terminal."
|
||||
|
||||
@@ -84,7 +84,7 @@ function _check_pause_process() {
|
||||
# We're forced to use $PODMAN because run_podman cannot be backgrounded
|
||||
# Also special logic to set a different argv0 to make sure the reexec still works:
|
||||
# https://github.com/containers/podman/issues/22672
|
||||
bash -c "exec -a argv0-podman $PODMAN run -i --name c_run $IMAGE sh -c '$SLEEPLOOP'" &
|
||||
bash -c "exec -a argv0-podman ${PODMAN_CMD[@]} run -i --name c_run $IMAGE sh -c '$SLEEPLOOP'" &
|
||||
local kidpid=$!
|
||||
|
||||
_test_sigproxy c_run $kidpid
|
||||
@@ -112,7 +112,7 @@ function _check_pause_process() {
|
||||
# Now again directly start podman run and make sure it can forward signals
|
||||
# We're forced to use $PODMAN because run_podman cannot be backgrounded
|
||||
local cname2=c2_$(random_string)
|
||||
$PODMAN run -i --name $cname2 $IMAGE sh -c "$SLEEPLOOP" &
|
||||
"${PODMAN_CMD[@]}" run -i --name $cname2 $IMAGE sh -c "$SLEEPLOOP" &
|
||||
local kidpid=$!
|
||||
|
||||
_test_sigproxy $cname2 $kidpid
|
||||
|
||||
@@ -152,7 +152,7 @@ RELABEL="system_u:object_r:container_file_t:s0"
|
||||
# Run `play kube` in the background as it will wait for the service
|
||||
# container to exit.
|
||||
timeout --foreground -v --kill=10 60 \
|
||||
$PODMAN play kube --service-container=true --log-driver journald $TESTYAML &>/dev/null &
|
||||
"${PODMAN_CMD[@]}" play kube --service-container=true --log-driver journald $TESTYAML &>/dev/null &
|
||||
|
||||
# Wait for the container to be running
|
||||
container_a=$PODCTRNAME
|
||||
@@ -569,7 +569,7 @@ EOF
|
||||
# Run `play kube` in the background as it will wait for the service
|
||||
# container to exit.
|
||||
timeout --foreground -v --kill=10 60 \
|
||||
$PODMAN play kube --service-container=true --log-driver journald $TESTYAML &>/dev/null &
|
||||
"${PODMAN_CMD[@]}" play kube --service-container=true --log-driver journald $TESTYAML &>/dev/null &
|
||||
|
||||
# The name of the service container is predictable: the first 12 characters
|
||||
# of the hash of the YAML file followed by the "-service" suffix
|
||||
@@ -662,7 +662,7 @@ spec:
|
||||
# on a running container; signaling during initialization
|
||||
# results in undefined behavior.
|
||||
logfile=$PODMAN_TMPDIR/kube-play.log
|
||||
$PODMAN kube play --wait $fname &> $logfile &
|
||||
"${PODMAN_CMD[@]}" kube play --wait $fname &> $logfile &
|
||||
local kidpid=$!
|
||||
|
||||
for try in {1..10}; do
|
||||
|
||||
@@ -63,6 +63,12 @@ EOF
|
||||
url="${PODMAN##*--url }"
|
||||
url="${url%% *}"
|
||||
op='='
|
||||
elif is_remote && [[ "${REMOTESYSTEM_TRANSPORT}" =~ tcp|tls|mtls ]]; then
|
||||
url="tcp://localhost:${REMOTESYSTEM_TCP_PORT}"
|
||||
op='='
|
||||
elif is_remote && [[ "${REMOTESYSTEM_TRANSPORT}" =~ unix ]]; then
|
||||
url="unix://${REMOTESYSTEM_UNIX_SOCK}"
|
||||
op='='
|
||||
fi
|
||||
# podman-remote test might run with --url so unset this because the socket will be used otherwise
|
||||
CONTAINERS_CONF_OVERRIDE=$compose_conf run_podman compose env
|
||||
|
||||
@@ -35,6 +35,46 @@ SYSTEMD_IMAGE=$PODMAN_SYSTEMD_IMAGE_FQN
|
||||
# Default timeout for a podman command.
|
||||
PODMAN_TIMEOUT=${PODMAN_TIMEOUT:-120}
|
||||
|
||||
function add_podman_args {
|
||||
declare -n arrayptr=$1
|
||||
|
||||
if is_remote ; then
|
||||
case "${REMOTESYSTEM_TRANSPORT}" in
|
||||
tcp|tls|mtls)
|
||||
arrayptr+=(--url="tcp://localhost:${REMOTESYSTEM_TCP_PORT}")
|
||||
;;
|
||||
unix)
|
||||
arrayptr+=(--url="unix://${REMOTESYSTEM_UNIX_SOCK}")
|
||||
esac
|
||||
case "${REMOTESYSTEM_TRANSPORT}" in
|
||||
tls|mtls)
|
||||
arrayptr+=(--tls-ca="${REMOTESYSTEM_TLS_CA_CRT}")
|
||||
;;
|
||||
esac
|
||||
case "${REMOTESYSTEM_TRANSPORT}" in
|
||||
mtls)
|
||||
arrayptr+=(
|
||||
--tls-cert="${REMOTESYSTEM_TLS_CLIENT_CRT}"
|
||||
--tls-key="${REMOTESYSTEM_TLS_CLIENT_KEY}"
|
||||
)
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
export REMOTESYSTEM_TLS_CA_CRT=${BATS_SUITE_TMPDIR}/remotesystem.ca.crt.pem
|
||||
export REMOTESYSTEM_TLS_CA_KEY=${BATS_SUITE_TMPDIR}/remotesystem.ca.key.pem
|
||||
export REMOTESYSTEM_TLS_SERVER_CRT=${BATS_SUITE_TMPDIR}/remotesystem.server.crt.pem
|
||||
export REMOTESYSTEM_TLS_SERVER_KEY=${BATS_SUITE_TMPDIR}/remotesystem.server.key.pem
|
||||
export REMOTESYSTEM_TLS_CLIENT_CRT=${BATS_SUITE_TMPDIR}/remotesystem.client.crt.pem
|
||||
export REMOTESYSTEM_TLS_CLIENT_KEY=${BATS_SUITE_TMPDIR}/remotesystem.client.key.pem
|
||||
export REMOTESYSTEM_TLS_BOGUS_CRT=${BATS_SUITE_TMPDIR}/remotesystem.bogus.crt.pem
|
||||
export REMOTESYSTEM_TLS_BOGUS_KEY=${BATS_SUITE_TMPDIR}/remotesystem.bogus.key.pem
|
||||
|
||||
# Full command to run podman, including remote flags. This is (re)set by basic_setup.
|
||||
PODMAN_CMD=()
|
||||
|
||||
# Prompt to display when logging podman commands; distinguish root/rootless
|
||||
_LOG_PROMPT='$'
|
||||
if [ $(id -u) -eq 0 ]; then
|
||||
@@ -168,6 +208,9 @@ function basic_setup() {
|
||||
# idea being that a large number of failures can show patterns.
|
||||
ASSERTION_FAILURES=
|
||||
immediate-assertion-failures
|
||||
|
||||
PODMAN_CMD=("${PODMAN}")
|
||||
add_podman_args PODMAN_CMD
|
||||
}
|
||||
|
||||
# bail-now is how we terminate a test upon assertion failure.
|
||||
@@ -291,7 +334,7 @@ function restore_image() {
|
||||
#######################
|
||||
function _run_podman_quiet() {
|
||||
# This should be the same as what run_podman() does.
|
||||
run timeout -v --foreground --kill=10 60 $PODMAN $_PODMAN_TEST_OPTS "$@"
|
||||
run timeout -v --foreground --kill=10 60 ${PODMAN_CMD[@]} $_PODMAN_TEST_OPTS "$@"
|
||||
if [[ $status -ne 0 ]]; then
|
||||
echo "# Error running command: podman $*"
|
||||
echo "$output"
|
||||
@@ -394,7 +437,7 @@ function clean_setup() {
|
||||
# Special case for timeout: check for locks (#18514)
|
||||
if [[ $status -eq 124 ]]; then
|
||||
echo "# [teardown] $_LOG_PROMPT podman system locks" >&3
|
||||
run $PODMAN system locks
|
||||
run "${PODMAN_CMD[@]}" system locks
|
||||
for line in "${lines[*]}"; do
|
||||
echo "# $line" >&3
|
||||
done
|
||||
@@ -512,11 +555,16 @@ function run_podman() {
|
||||
silence127="!"
|
||||
fi
|
||||
|
||||
podman_args=()
|
||||
add_podman_args podman_args
|
||||
|
||||
|
||||
# stdout is only emitted upon error; this printf is to help in debugging
|
||||
printf "\n%s %s %s %s\n" "$(timestamp)" "$_LOG_PROMPT" "$PODMAN" "$*"
|
||||
printf "\n%s %s %s %s\n" "$(timestamp)" "$_LOG_PROMPT" $PODMAN "${podman_args[@]}" "$*"
|
||||
|
||||
# BATS hangs if a subprocess remains and keeps FD 3 open; this happens
|
||||
# if podman crashes unexpectedly without cleaning up subprocesses.
|
||||
run $silence127 timeout --foreground -v --kill=10 $PODMAN_TIMEOUT $PODMAN $_PODMAN_TEST_OPTS "$@" 3>/dev/null
|
||||
run $silence127 timeout --foreground -v --kill=10 $PODMAN_TIMEOUT $PODMAN "${podman_args[@]}" $_PODMAN_TEST_OPTS "$@" 3>/dev/null
|
||||
# without "quotes", multiple lines are glommed together into one
|
||||
if [ -n "$output" ]; then
|
||||
echo "$(timestamp) $output"
|
||||
@@ -1374,6 +1422,118 @@ function wait_for_restart_count() {
|
||||
done
|
||||
}
|
||||
|
||||
function gen-cert-pair {
|
||||
cn=$1 key=$2 cert=$3
|
||||
shift 3
|
||||
openssl req -x509 \
|
||||
-quiet \
|
||||
-nodes \
|
||||
-newkey rsa:4096 -keyout "${key}" \
|
||||
-out "${cert}" \
|
||||
-days 1 \
|
||||
-subj "/C=??/ST=System/L=Test/O=Containers/OU=Podman/CN=${cn}" \
|
||||
"$@"
|
||||
}
|
||||
|
||||
function gen-signed-cert-pair {
|
||||
cn=$1 key=$2 cert=$3 ca_key=$4 ca_cert=$5
|
||||
shift 5
|
||||
gen-cert-pair "${cn}" \
|
||||
"${key}" "${cert}" \
|
||||
-CAkey "${ca_key}" -CA "${ca_cert}" \
|
||||
"$@"
|
||||
}
|
||||
|
||||
function gen-tls {
|
||||
rm -f \
|
||||
"${REMOTESYSTEM_TLS_CA_KEY}" "${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
"${REMOTESYSTEM_TLS_CLIENT_KEY}" "${REMOTESYSTEM_TLS_CLIENT_CRT}" \
|
||||
"${REMOTESYSTEM_TLS_SERVER_KEY}" "${REMOTESYSTEM_TLS_SERVER_CRT}" \
|
||||
"${REMOTESYSTEM_TLS_BOGUS_KEY}" "${REMOTESYSTEM_TLS_BOGUS_CRT}"
|
||||
|
||||
# CA
|
||||
gen-cert-pair "ca" \
|
||||
"${REMOTESYSTEM_TLS_CA_KEY}" "${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
-addext basicConstraints=critical,CA:TRUE,pathlen:1
|
||||
# Client, signed by CA
|
||||
gen-signed-cert-pair "client" \
|
||||
"${REMOTESYSTEM_TLS_CLIENT_KEY}" "${REMOTESYSTEM_TLS_CLIENT_CRT}" \
|
||||
"${REMOTESYSTEM_TLS_CA_KEY}" "${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
|
||||
# Server, signed by CA, valid for localhost, 127.0.0.1
|
||||
# NOTE: Go refuses certs without SAN's
|
||||
gen-signed-cert-pair "localhost" \
|
||||
"${REMOTESYSTEM_TLS_SERVER_KEY}" "${REMOTESYSTEM_TLS_SERVER_CRT}" \
|
||||
"${REMOTESYSTEM_TLS_CA_KEY}" "${REMOTESYSTEM_TLS_CA_CRT}" \
|
||||
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
|
||||
|
||||
# Bogus, self-signed
|
||||
gen-cert-pair "bogus" \
|
||||
"${REMOTESYSTEM_TLS_BOGUS_KEY}" "${REMOTESYSTEM_TLS_BOGUS_CRT}" \
|
||||
-addext basicConstraints=critical,CA:TRUE,pathlen:1
|
||||
}
|
||||
|
||||
|
||||
function systemd-run-user {
|
||||
args=()
|
||||
if [ "${UID}" != '0' ]; then
|
||||
args+=(--user)
|
||||
fi
|
||||
systemd-run "${args[@]}" "$@"
|
||||
}
|
||||
|
||||
function systemctl-user {
|
||||
args=()
|
||||
if [ "${UID}" != '0' ]; then
|
||||
args+=(--user)
|
||||
fi
|
||||
systemctl "${args[@]}" "$@"
|
||||
}
|
||||
|
||||
SUITE_SERVICE_NAME="podman-service-$(random_string)"
|
||||
SUITE_PIDFILE="${BATS_SUITE_TMPDIR}/podman-system-service.pid"
|
||||
function start-suite-podman-system-service {
|
||||
service_args=()
|
||||
case "${REMOTESYSTEM_TRANSPORT}" in
|
||||
tls|mtls)
|
||||
service_args+=(
|
||||
--tls-cert="${REMOTESYSTEM_TLS_SERVER_CRT}"
|
||||
--tls-key="${REMOTESYSTEM_TLS_SERVER_KEY}"
|
||||
)
|
||||
;;
|
||||
esac
|
||||
case "${REMOTESYSTEM_TRANSPORT}" in
|
||||
mtls)
|
||||
service_args+=(--tls-client-ca="${REMOTESYSTEM_TLS_CA_CRT}")
|
||||
;;
|
||||
esac
|
||||
case "${REMOTESYSTEM_TRANSPORT}" in
|
||||
tcp|tls|mtls)
|
||||
service_args+=("tcp://localhost:${REMOTESYSTEM_TCP_PORT}")
|
||||
;;
|
||||
unix)
|
||||
rm "${REMOTESYSTEM_UNIX_SOCK}"
|
||||
service_args+=("unix://${REMOTESYSTEM_UNIX_SOCK}")
|
||||
esac
|
||||
|
||||
# TODO: In the future, use systemd if possible
|
||||
# systemd-run-user --unit=$SUITE_SERVICE_NAME ${PODMAN%%-remote*} system service "${service_args[@]}" --time=0
|
||||
${PODMAN%%-remote*} system service "${service_args[@]}" --time=0 &> "${PODMAN_SERVER_LOG:-/dev/null}" &
|
||||
echo $! > "${SUITE_PIDFILE}"
|
||||
|
||||
retry=5
|
||||
while [ $retry -ge 0 ]; do
|
||||
echo Waiting for system service...
|
||||
sleep 1
|
||||
"${PODMAN_CMD[@]}" system info && break
|
||||
retry=$(expr $retry - 1)
|
||||
done
|
||||
if [ $retry -lt 0 ]; then
|
||||
echo "Error: ./bin/podman system service did not come up" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# END miscellaneous tools
|
||||
###############################################################################
|
||||
|
||||
@@ -8,6 +8,7 @@ load helpers
|
||||
load helpers.network
|
||||
load helpers.registry
|
||||
|
||||
|
||||
# Create common environment just in case we end up needing a registry.
|
||||
# These environment variables will be available to all tests.
|
||||
function setup_suite() {
|
||||
@@ -17,6 +18,20 @@ function setup_suite() {
|
||||
IFS="
|
||||
"
|
||||
|
||||
# These are set/generated even for non-remote tests because some local tests still create their
|
||||
# own system service.
|
||||
export REMOTESYSTEM_UNIX_SOCK=$(mktemp ${BATS_SUITE_TMPDIR}/remotesystem.podman.XXXXXX.sock)
|
||||
export REMOTESYSTEM_TCP_PORT=$(random_free_port 27000-27999)
|
||||
gen-tls
|
||||
|
||||
PODMAN_CMD=("${PODMAN}")
|
||||
add_podman_args PODMAN_CMD
|
||||
|
||||
if is_remote; then
|
||||
echo "Running remote system tests with transport ${REMOTESYSTEM_TRANSPORT}"
|
||||
start-suite-podman-system-service
|
||||
fi
|
||||
|
||||
export PODMAN_LOGIN_WORKDIR="$BATS_SUITE_TMPDIR/podman-bats-registry"
|
||||
mkdir "$PODMAN_LOGIN_WORKDIR"
|
||||
|
||||
@@ -64,6 +79,15 @@ function teardown_suite() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if is_remote; then
|
||||
# See function start-suite-podman-system-service
|
||||
# run systemctl-user stop "$SUITE_SERVICE_NAME"
|
||||
# journalctl -u "${SUITE_SERVICE_NAME}" | tee ${PODMAN_SERVER_LOG:-/dev/null}
|
||||
local system_service_pid=$(cat "${SUITE_PIDFILE}")
|
||||
kill -sINT "${system_service_pid}"
|
||||
wait "${system_service_pid}"
|
||||
fi
|
||||
|
||||
return $exit_code
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,11 @@ package utils
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
@@ -14,9 +18,6 @@ import (
|
||||
"time"
|
||||
|
||||
crypto_rand "crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
@@ -63,19 +64,29 @@ type PodmanTestCommon interface {
|
||||
|
||||
// PodmanTest struct for command line options
|
||||
type PodmanTest struct {
|
||||
ImageCacheDir string
|
||||
ImageCacheFS string
|
||||
NetworkBackend NetworkBackend
|
||||
DatabaseBackend string
|
||||
PodmanBinary string
|
||||
PodmanMakeOptions func(args []string, options PodmanExecOptions) []string
|
||||
RemoteCommand *exec.Cmd
|
||||
RemotePodmanBinary string
|
||||
RemoteSession *os.Process
|
||||
RemoteSocket string
|
||||
RemoteSocketLock string // If not "", should be removed _after_ RemoteSocket is removed
|
||||
RemoteTest bool
|
||||
TempDir string
|
||||
ImageCacheDir string
|
||||
ImageCacheFS string
|
||||
NetworkBackend NetworkBackend
|
||||
DatabaseBackend string
|
||||
PodmanBinary string
|
||||
PodmanMakeOptions func(args []string, options PodmanExecOptions) []string
|
||||
RemoteCommand *exec.Cmd
|
||||
RemotePodmanBinary string
|
||||
RemoteSession *os.Process
|
||||
RemoteSocket string
|
||||
RemoteSocketScheme string
|
||||
RemoteSocketLock string // If not "", should be removed _after_ RemoteSocket is removed
|
||||
RemoteTLSClientCAFile string
|
||||
RemoteTLSClientCAPool *x509.CertPool
|
||||
RemoteTLSClientCerts []tls.Certificate
|
||||
RemoteTLSServerCertFile string
|
||||
RemoteTLSServerKeyFile string
|
||||
RemoteTLSServerCAFile string
|
||||
RemoteTLSServerCAPool *x509.CertPool
|
||||
RemoteTLSClientCertFile string
|
||||
RemoteTLSClientKeyFile string
|
||||
RemoteTest bool
|
||||
TempDir string
|
||||
}
|
||||
|
||||
// PodmanSession wraps the gexec.session so we can extend it
|
||||
@@ -229,7 +240,7 @@ func (p *PodmanTest) NumberOfPods() int {
|
||||
// GetContainerStatus returns the containers state.
|
||||
// This function assumes only one container is active.
|
||||
func (p *PodmanTest) GetContainerStatus() string {
|
||||
var podmanArgs = []string{"ps"}
|
||||
podmanArgs := []string{"ps"}
|
||||
podmanArgs = append(podmanArgs, "--all", "--format={{.Status}}")
|
||||
session := p.PodmanExecBaseWithOptions(podmanArgs, PodmanExecOptions{
|
||||
NoCache: true,
|
||||
|
||||
11
vendor/github.com/google/pprof/profile/merge.go
generated
vendored
11
vendor/github.com/google/pprof/profile/merge.go
generated
vendored
@@ -17,6 +17,7 @@ package profile
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"slices"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -78,12 +79,10 @@ func Merge(srcs []*Profile) (*Profile, error) {
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range p.Sample {
|
||||
if isZeroSample(s) {
|
||||
// If there are any zero samples, re-merge the profile to GC
|
||||
// them.
|
||||
return Merge([]*Profile{p})
|
||||
}
|
||||
if slices.ContainsFunc(p.Sample, isZeroSample) {
|
||||
// If there are any zero samples, re-merge the profile to GC
|
||||
// them.
|
||||
return Merge([]*Profile{p})
|
||||
}
|
||||
|
||||
return p, nil
|
||||
|
||||
20
vendor/github.com/google/pprof/profile/profile.go
generated
vendored
20
vendor/github.com/google/pprof/profile/profile.go
generated
vendored
@@ -24,6 +24,7 @@ import (
|
||||
"math"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -734,12 +735,7 @@ func (p *Profile) RemoveLabel(key string) {
|
||||
|
||||
// HasLabel returns true if a sample has a label with indicated key and value.
|
||||
func (s *Sample) HasLabel(key, value string) bool {
|
||||
for _, v := range s.Label[key] {
|
||||
if v == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(s.Label[key], value)
|
||||
}
|
||||
|
||||
// SetNumLabel sets the specified key to the specified value for all samples in the
|
||||
@@ -852,7 +848,17 @@ func (p *Profile) HasFileLines() bool {
|
||||
// "[vdso]", "[vsyscall]" and some others, see the code.
|
||||
func (m *Mapping) Unsymbolizable() bool {
|
||||
name := filepath.Base(m.File)
|
||||
return strings.HasPrefix(name, "[") || strings.HasPrefix(name, "linux-vdso") || strings.HasPrefix(m.File, "/dev/dri/") || m.File == "//anon"
|
||||
switch {
|
||||
case strings.HasPrefix(name, "["):
|
||||
case strings.HasPrefix(name, "linux-vdso"):
|
||||
case strings.HasPrefix(m.File, "/dev/dri/"):
|
||||
case m.File == "//anon":
|
||||
case m.File == "":
|
||||
case strings.HasPrefix(m.File, "/memfd:"):
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Copy makes a fully independent copy of a profile.
|
||||
|
||||
9
vendor/github.com/google/pprof/profile/prune.go
generated
vendored
9
vendor/github.com/google/pprof/profile/prune.go
generated
vendored
@@ -19,6 +19,7 @@ package profile
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -40,13 +41,7 @@ func simplifyFunc(f string) string {
|
||||
// Account for unsimplified names -- try to remove the argument list by trimming
|
||||
// starting from the first '(', but skipping reserved names that have '('.
|
||||
for _, ind := range bracketRx.FindAllStringSubmatchIndex(funcName, -1) {
|
||||
foundReserved := false
|
||||
for _, res := range reservedNames {
|
||||
if funcName[ind[0]:ind[1]] == res {
|
||||
foundReserved = true
|
||||
break
|
||||
}
|
||||
}
|
||||
foundReserved := slices.Contains(reservedNames, funcName[ind[0]:ind[1]])
|
||||
if !foundReserved {
|
||||
funcName = funcName[:ind[0]]
|
||||
break
|
||||
|
||||
11
vendor/go.podman.io/common/libimage/copier.go
generated
vendored
11
vendor/go.podman.io/common/libimage/copier.go
generated
vendored
@@ -9,6 +9,7 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -396,7 +397,7 @@ func (c *Copier) copyInternal(ctx context.Context, source, destination types.Ima
|
||||
// TimeoutStartSec=, the service manager will allow the service to continue to start, provided the
|
||||
// service repeats "EXTEND_TIMEOUT_USEC=..." within the interval specified until the service startup
|
||||
// status is finished by "READY=1"."
|
||||
extendValue := []byte(fmt.Sprintf("EXTEND_TIMEOUT_USEC=%d", extension.Microseconds()))
|
||||
extendValue := fmt.Appendf(nil, "EXTEND_TIMEOUT_USEC=%d", extension.Microseconds())
|
||||
extendTimeout := func() {
|
||||
if _, err := conn.Write(extendValue); err != nil {
|
||||
logrus.Errorf("Increasing EXTEND_TIMEOUT_USEC failed: %v", err)
|
||||
@@ -555,11 +556,9 @@ func checkRegistrySourcesAllows(dest types.ImageReference) (insecure *bool, err
|
||||
return nil, fmt.Errorf("registry %q denied by policy: not in allowed registries list (%s)", reference.Domain(dref), registrySources)
|
||||
}
|
||||
|
||||
for _, insecureDomain := range sources.InsecureRegistries {
|
||||
if insecureDomain == reference.Domain(dref) {
|
||||
insecure := true
|
||||
return &insecure, nil
|
||||
}
|
||||
if slices.Contains(sources.InsecureRegistries, reference.Domain(dref)) {
|
||||
insecure := true
|
||||
return &insecure, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
||||
12
vendor/go.podman.io/common/libimage/filter/filter.go
generated
vendored
12
vendor/go.podman.io/common/libimage/filter/filter.go
generated
vendored
@@ -24,25 +24,25 @@ type SearchFilter struct {
|
||||
func ParseSearchFilter(filter []string) (*SearchFilter, error) {
|
||||
sFilter := new(SearchFilter)
|
||||
for _, f := range filter {
|
||||
arr := strings.SplitN(f, "=", 2)
|
||||
switch arr[0] {
|
||||
keyword, value, ok := strings.Cut(f, "=")
|
||||
switch keyword {
|
||||
case define.SearchFilterStars:
|
||||
if len(arr) < 2 {
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid filter %q, should be stars=<value>", filter)
|
||||
}
|
||||
stars, err := strconv.Atoi(arr[1])
|
||||
stars, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("incorrect value type for stars filter: %w", err)
|
||||
}
|
||||
sFilter.Stars = stars
|
||||
case define.SearchFilterAutomated:
|
||||
if len(arr) == 2 && arr[1] == "false" {
|
||||
if ok && value == "false" {
|
||||
sFilter.IsAutomated = types.OptionalBoolFalse
|
||||
} else {
|
||||
sFilter.IsAutomated = types.OptionalBoolTrue
|
||||
}
|
||||
case define.SearchFilterOfficial:
|
||||
if len(arr) == 2 && arr[1] == "false" {
|
||||
if ok && value == "false" {
|
||||
sFilter.IsOfficial = types.OptionalBoolFalse
|
||||
} else {
|
||||
sFilter.IsOfficial = types.OptionalBoolTrue
|
||||
|
||||
10
vendor/go.podman.io/common/libimage/filters.go
generated
vendored
10
vendor/go.podman.io/common/libimage/filters.go
generated
vendored
@@ -89,18 +89,16 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp
|
||||
var key, value string
|
||||
var filter filterFunc
|
||||
negate := false
|
||||
split := strings.SplitN(f, "!=", 2)
|
||||
if len(split) == 2 {
|
||||
key, value, ok := strings.Cut(f, "!=")
|
||||
if ok {
|
||||
negate = true
|
||||
} else {
|
||||
split = strings.SplitN(f, "=", 2)
|
||||
if len(split) != 2 {
|
||||
key, value, ok = strings.Cut(f, "=")
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf(filterInvalidValue, f)
|
||||
}
|
||||
}
|
||||
|
||||
key = split[0]
|
||||
value = split[1]
|
||||
switch key {
|
||||
case "after", "since":
|
||||
img, err := r.time(key, value)
|
||||
|
||||
17
vendor/go.podman.io/common/libimage/image.go
generated
vendored
17
vendor/go.podman.io/common/libimage/image.go
generated
vendored
@@ -7,6 +7,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -173,12 +174,7 @@ func (i *Image) Digests() []digest.Digest {
|
||||
// hasDigest returns whether the specified value matches any digest of the
|
||||
// image.
|
||||
func (i *Image) hasDigest(wantedDigest digest.Digest) bool {
|
||||
for _, d := range i.Digests() {
|
||||
if d == wantedDigest {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(i.Digests(), wantedDigest)
|
||||
}
|
||||
|
||||
// containsDigestPrefix returns whether the specified value matches any digest of the
|
||||
@@ -638,16 +634,9 @@ func (i *Image) Untag(name string) error {
|
||||
|
||||
name = ref.String()
|
||||
|
||||
foundName := false
|
||||
for _, n := range i.Names() {
|
||||
if n == name {
|
||||
foundName = true
|
||||
break
|
||||
}
|
||||
}
|
||||
// Return an error if the name is not found, the c/storage
|
||||
// RemoveNames() API does not create one if no match is found.
|
||||
if !foundName {
|
||||
if !slices.Contains(i.Names(), name) {
|
||||
return fmt.Errorf("%s: %w", name, errTagUnknown)
|
||||
}
|
||||
|
||||
|
||||
31
vendor/go.podman.io/common/libimage/image_config.go
generated
vendored
31
vendor/go.podman.io/common/libimage/image_config.go
generated
vendored
@@ -40,17 +40,17 @@ func ImageConfigFromChanges(changes []string) (*ImageConfig, error) { // nolint:
|
||||
for _, change := range changes {
|
||||
// First, let's assume proper Dockerfile format - space
|
||||
// separator between instruction and value
|
||||
split := strings.SplitN(change, " ", 2)
|
||||
outerKey, value, ok := strings.Cut(change, " ")
|
||||
|
||||
if len(split) != 2 {
|
||||
split = strings.SplitN(change, "=", 2)
|
||||
if len(split) != 2 {
|
||||
if !ok {
|
||||
outerKey, value, ok = strings.Cut(change, "=")
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid change %q - must be formatted as KEY VALUE", change)
|
||||
}
|
||||
}
|
||||
|
||||
outerKey := strings.ToUpper(strings.TrimSpace(split[0]))
|
||||
value := strings.TrimSpace(split[1])
|
||||
outerKey = strings.ToUpper(strings.TrimSpace(outerKey))
|
||||
value = strings.TrimSpace(value)
|
||||
switch outerKey {
|
||||
case "USER":
|
||||
// Assume literal contents are the user.
|
||||
@@ -96,18 +96,11 @@ func ImageConfigFromChanges(changes []string) (*ImageConfig, error) { // nolint:
|
||||
// For now: we only support key=value
|
||||
// We will attempt to strip quotation marks if present.
|
||||
|
||||
var key, val string
|
||||
|
||||
splitEnv := strings.SplitN(value, "=", 2)
|
||||
key = splitEnv[0]
|
||||
key, val, _ := strings.Cut(value, "=") // val is "" if there is no "="
|
||||
// We do need a key
|
||||
if key == "" {
|
||||
return nil, fmt.Errorf("invalid change %q - ENV must have at least one argument", change)
|
||||
}
|
||||
// Perfectly valid to not have a value
|
||||
if len(splitEnv) == 2 {
|
||||
val = splitEnv[1]
|
||||
}
|
||||
|
||||
if strings.HasPrefix(key, `"`) && strings.HasSuffix(key, `"`) {
|
||||
key = strings.TrimPrefix(strings.TrimSuffix(key, `"`), `"`)
|
||||
@@ -192,17 +185,11 @@ func ImageConfigFromChanges(changes []string) (*ImageConfig, error) { // nolint:
|
||||
// Potentially problematic: LABEL might theoretically
|
||||
// allow an = in the key? If people really do this, we
|
||||
// may need to investigate more advanced parsing.
|
||||
var (
|
||||
key, val string
|
||||
)
|
||||
|
||||
splitLabel := strings.SplitN(value, "=", 2)
|
||||
key, val, ok := strings.Cut(value, "=")
|
||||
// Unlike ENV, LABEL must have a value
|
||||
if len(splitLabel) != 2 {
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid change %q - LABEL must be formatted key=value", change)
|
||||
}
|
||||
key = splitLabel[0]
|
||||
val = splitLabel[1]
|
||||
|
||||
if strings.HasPrefix(key, `"`) && strings.HasSuffix(key, `"`) {
|
||||
key = strings.TrimPrefix(strings.TrimSuffix(key, `"`), `"`)
|
||||
|
||||
6
vendor/go.podman.io/common/libimage/manifest_list.go
generated
vendored
6
vendor/go.podman.io/common/libimage/manifest_list.go
generated
vendored
@@ -303,10 +303,8 @@ func (m *ManifestList) LookupInstance(ctx context.Context, architecture, os, var
|
||||
}
|
||||
|
||||
for _, image := range allImages {
|
||||
for _, imageDigest := range append(image.Digests(), image.Digest()) {
|
||||
if imageDigest == instanceDigest {
|
||||
return image, nil
|
||||
}
|
||||
if slices.Contains(image.Digests(), instanceDigest) || instanceDigest == image.Digest() {
|
||||
return image, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
6
vendor/go.podman.io/common/libimage/manifests/manifests.go
generated
vendored
6
vendor/go.podman.io/common/libimage/manifests/manifests.go
generated
vendored
@@ -252,10 +252,8 @@ func (l *list) InstanceByFile(file string) (digest.Digest, error) {
|
||||
return "", err
|
||||
}
|
||||
for instanceDigest, files := range l.artifacts.Files {
|
||||
for _, file := range files {
|
||||
if file == abs {
|
||||
return instanceDigest, nil
|
||||
}
|
||||
if slices.Contains(files, abs) {
|
||||
return instanceDigest, nil
|
||||
}
|
||||
}
|
||||
return "", os.ErrNotExist
|
||||
|
||||
6
vendor/go.podman.io/common/libimage/pull.go
generated
vendored
6
vendor/go.podman.io/common/libimage/pull.go
generated
vendored
@@ -253,8 +253,8 @@ func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference,
|
||||
storageName = imageName
|
||||
|
||||
case ociTransport.Transport.Name():
|
||||
split := strings.SplitN(ref.StringWithinTransport(), ":", 2)
|
||||
if len(split) == 1 || split[1] == "" {
|
||||
_, refName, ok := strings.Cut(ref.StringWithinTransport(), ":")
|
||||
if !ok || refName == "" {
|
||||
// Same trick as for the dir transport: we cannot use
|
||||
// the path to a directory as the name.
|
||||
storageName, err = getImageID(ctx, ref, nil)
|
||||
@@ -263,7 +263,7 @@ func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference,
|
||||
}
|
||||
imageName = "sha256:" + storageName[1:]
|
||||
} else { // If the OCI-reference includes an image reference, use it
|
||||
storageName = split[1]
|
||||
storageName = refName
|
||||
imageName = storageName
|
||||
}
|
||||
|
||||
|
||||
28
vendor/go.podman.io/common/libimage/search.go
generated
vendored
28
vendor/go.podman.io/common/libimage/search.go
generated
vendored
@@ -94,11 +94,11 @@ func (r *Runtime) Search(ctx context.Context, term string, options *SearchOption
|
||||
// that we cannot use the reference parser from the containers/image
|
||||
// library as the search term may container arbitrary input such as
|
||||
// wildcards. See bugzilla.redhat.com/show_bug.cgi?id=1846629.
|
||||
spl := strings.SplitN(term, "/", 2)
|
||||
perhapsRegistry, perhapsTerm, ok := strings.Cut(term, "/")
|
||||
switch {
|
||||
case len(spl) > 1:
|
||||
searchRegistries = []string{spl[0]}
|
||||
term = spl[1]
|
||||
case ok:
|
||||
searchRegistries = []string{perhapsRegistry}
|
||||
term = perhapsTerm
|
||||
case len(options.Registries) > 0:
|
||||
searchRegistries = options.Registries
|
||||
default:
|
||||
@@ -203,15 +203,9 @@ func (r *Runtime) searchImageInRegistry(ctx context.Context, term, registry stri
|
||||
// limit is the number of results to output
|
||||
// if the total number of results is less than the limit, output all
|
||||
// if the limit has been set by the user, output those number of queries
|
||||
limit = searchMaxQueries
|
||||
if len(results) < limit {
|
||||
limit = len(results)
|
||||
}
|
||||
limit = min(len(results), searchMaxQueries)
|
||||
if options.Limit != 0 {
|
||||
limit = len(results)
|
||||
if options.Limit < len(results) {
|
||||
limit = options.Limit
|
||||
}
|
||||
limit = min(len(results), options.Limit)
|
||||
}
|
||||
|
||||
paramsArr := []SearchResult{}
|
||||
@@ -264,15 +258,9 @@ func searchRepositoryTags(ctx context.Context, sys *types.SystemContext, registr
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting repository tags: %v", err)
|
||||
}
|
||||
limit := searchMaxQueries
|
||||
if len(tags) < limit {
|
||||
limit = len(tags)
|
||||
}
|
||||
limit := min(len(tags), searchMaxQueries)
|
||||
if options.Limit != 0 {
|
||||
limit = len(tags)
|
||||
if options.Limit < limit {
|
||||
limit = options.Limit
|
||||
}
|
||||
limit = min(len(tags), options.Limit)
|
||||
}
|
||||
paramsArr := []SearchResult{}
|
||||
for i := range limit {
|
||||
|
||||
4
vendor/go.podman.io/common/libnetwork/cni/cni_conversion.go
generated
vendored
4
vendor/go.podman.io/common/libnetwork/cni/cni_conversion.go
generated
vendored
@@ -355,9 +355,7 @@ func convertSpecgenPortsToCNIPorts(ports []types.PortMapping) ([]cniPortMapEntry
|
||||
if port.Protocol == "" {
|
||||
return nil, errors.New("port protocol should not be empty")
|
||||
}
|
||||
protocols := strings.Split(port.Protocol, ",")
|
||||
|
||||
for _, protocol := range protocols {
|
||||
for protocol := range strings.SplitSeq(port.Protocol, ",") {
|
||||
if !slices.Contains([]string{"tcp", "udp", "sctp"}, protocol) {
|
||||
return nil, fmt.Errorf("unknown port protocol %s", protocol)
|
||||
}
|
||||
|
||||
6
vendor/go.podman.io/common/libnetwork/cni/run.go
generated
vendored
6
vendor/go.podman.io/common/libnetwork/cni/run.go
generated
vendored
@@ -177,9 +177,9 @@ func getRuntimeConfig(netns, conName, conID, networkName string, ports []cniPort
|
||||
}
|
||||
|
||||
// Propagate environment CNI_ARGS
|
||||
for _, kvpairs := range strings.Split(os.Getenv("CNI_ARGS"), ";") {
|
||||
if keyval := strings.SplitN(kvpairs, "=", 2); len(keyval) == 2 {
|
||||
rt.Args = append(rt.Args, [2]string{keyval[0], keyval[1]})
|
||||
for kvpairs := range strings.SplitSeq(os.Getenv("CNI_ARGS"), ";") {
|
||||
if key, val, ok := strings.Cut(kvpairs, "="); ok {
|
||||
rt.Args = append(rt.Args, [2]string{key, val})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
13
vendor/go.podman.io/common/libnetwork/etchosts/hosts.go
generated
vendored
13
vendor/go.podman.io/common/libnetwork/etchosts/hosts.go
generated
vendored
@@ -236,24 +236,23 @@ func checkIfEntryExists(current HostEntry, entries HostEntries) bool {
|
||||
func parseExtraHosts(extraHosts []string, hostContainersInternalIP string) (HostEntries, error) {
|
||||
entries := make(HostEntries, 0, len(extraHosts))
|
||||
for _, entry := range extraHosts {
|
||||
values := strings.SplitN(entry, ":", 2)
|
||||
if len(values) != 2 {
|
||||
namesString, ip, ok := strings.Cut(entry, ":")
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to parse host entry %q: incorrect format", entry)
|
||||
}
|
||||
if values[0] == "" {
|
||||
if namesString == "" {
|
||||
return nil, fmt.Errorf("hostname in host entry %q is empty", entry)
|
||||
}
|
||||
if values[1] == "" {
|
||||
if ip == "" {
|
||||
return nil, fmt.Errorf("IP address in host entry %q is empty", entry)
|
||||
}
|
||||
ip := values[1]
|
||||
if values[1] == HostGateway {
|
||||
if ip == HostGateway {
|
||||
if hostContainersInternalIP == "" {
|
||||
return nil, fmt.Errorf("unable to replace %q of host entry %q: host containers internal IP address is empty", HostGateway, entry)
|
||||
}
|
||||
ip = hostContainersInternalIP
|
||||
}
|
||||
names := strings.Split(values[0], ";")
|
||||
names := strings.Split(namesString, ";")
|
||||
e := HostEntry{IP: ip, Names: names}
|
||||
entries = append(entries, e)
|
||||
}
|
||||
|
||||
3
vendor/go.podman.io/common/libnetwork/pasta/pasta_linux.go
generated
vendored
3
vendor/go.podman.io/common/libnetwork/pasta/pasta_linux.go
generated
vendored
@@ -212,8 +212,7 @@ func createPastaArgs(opts *SetupOptions) ([]string, []string, []string, error) {
|
||||
}
|
||||
|
||||
for _, i := range opts.Ports {
|
||||
protocols := strings.Split(i.Protocol, ",")
|
||||
for _, protocol := range protocols {
|
||||
for protocol := range strings.SplitSeq(i.Protocol, ",") {
|
||||
var addr string
|
||||
|
||||
if i.HostIP != "" {
|
||||
|
||||
3
vendor/go.podman.io/common/libnetwork/resolvconf/resolvconf.go
generated
vendored
3
vendor/go.podman.io/common/libnetwork/resolvconf/resolvconf.go
generated
vendored
@@ -76,9 +76,8 @@ func filterResolvDNS(resolvConf []byte, ipv6Enabled bool, netnsEnabled bool) []b
|
||||
|
||||
// getLines parses input into lines and strips away comments.
|
||||
func getLines(input []byte) [][]byte {
|
||||
lines := bytes.Split(input, []byte("\n"))
|
||||
var output [][]byte
|
||||
for _, currentLine := range lines {
|
||||
for currentLine := range bytes.SplitSeq(input, []byte("\n")) {
|
||||
commentIndex := bytes.Index(currentLine, []byte("#"))
|
||||
if commentIndex == -1 {
|
||||
output = append(output, currentLine)
|
||||
|
||||
9
vendor/go.podman.io/common/libnetwork/slirp4netns/const.go
generated
vendored
9
vendor/go.podman.io/common/libnetwork/slirp4netns/const.go
generated
vendored
@@ -3,14 +3,7 @@ package slirp4netns
|
||||
import "net"
|
||||
|
||||
const (
|
||||
ipv6ConfDefaultAcceptDadSysctl = "/proc/sys/net/ipv6/conf/default/accept_dad"
|
||||
BinaryName = "slirp4netns"
|
||||
|
||||
// defaultMTU the default MTU override.
|
||||
defaultMTU = 65520
|
||||
|
||||
// default slirp4ns subnet.
|
||||
defaultSubnet = "10.0.2.0/24"
|
||||
BinaryName = "slirp4netns"
|
||||
)
|
||||
|
||||
// SetupResult return type from Setup().
|
||||
|
||||
11
vendor/go.podman.io/common/libnetwork/slirp4netns/const_linux.go
generated
vendored
Normal file
11
vendor/go.podman.io/common/libnetwork/slirp4netns/const_linux.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package slirp4netns
|
||||
|
||||
const (
|
||||
ipv6ConfDefaultAcceptDadSysctl = "/proc/sys/net/ipv6/conf/default/accept_dad"
|
||||
|
||||
// defaultMTU the default MTU override.
|
||||
defaultMTU = 65520
|
||||
|
||||
// default slirp4ns subnet.
|
||||
defaultSubnet = "10.0.2.0/24"
|
||||
)
|
||||
8
vendor/go.podman.io/common/libnetwork/slirp4netns/slirp4netns.go
generated
vendored
8
vendor/go.podman.io/common/libnetwork/slirp4netns/slirp4netns.go
generated
vendored
@@ -124,11 +124,10 @@ func parseNetworkOptions(config *config.Config, extraOptions []string) (*network
|
||||
enableIPv6: true,
|
||||
}
|
||||
for _, o := range options {
|
||||
parts := strings.SplitN(o, "=", 2)
|
||||
if len(parts) < 2 {
|
||||
option, value, ok := strings.Cut(o, "=")
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown option for slirp4netns: %q", o)
|
||||
}
|
||||
option, value := parts[0], parts[1]
|
||||
switch option {
|
||||
case "cidr":
|
||||
ipv4, _, err := net.ParseCIDR(value)
|
||||
@@ -639,8 +638,7 @@ func setupRootlessPortMappingViaSlirp(ports []types.PortMapping, cmd *exec.Cmd,
|
||||
// for each port we want to add we need to open a connection to the slirp4netns control socket
|
||||
// and send the add_hostfwd command.
|
||||
for _, port := range ports {
|
||||
protocols := strings.Split(port.Protocol, ",")
|
||||
for _, protocol := range protocols {
|
||||
for protocol := range strings.SplitSeq(port.Protocol, ",") {
|
||||
hostIP := port.HostIP
|
||||
if hostIP == "" {
|
||||
hostIP = "0.0.0.0"
|
||||
|
||||
8
vendor/go.podman.io/common/pkg/apparmor/apparmor_linux.go
generated
vendored
8
vendor/go.podman.io/common/pkg/apparmor/apparmor_linux.go
generated
vendored
@@ -208,14 +208,14 @@ func parseAAParserVersion(output string) (int, error) {
|
||||
// AppArmor parser version 2.9.1
|
||||
// Copyright (C) 1999-2008 Novell Inc.
|
||||
// Copyright 2009-2012 Canonical Ltd.
|
||||
lines := strings.SplitN(output, "\n", 2)
|
||||
words := strings.Split(lines[0], " ")
|
||||
firstLine, _, _ := strings.Cut(output, "\n")
|
||||
words := strings.Split(firstLine, " ")
|
||||
version := words[len(words)-1]
|
||||
|
||||
// trim "-beta1" suffix from version="3.0.0-beta1" if exists
|
||||
version = strings.SplitN(version, "-", 2)[0]
|
||||
version, _, _ = strings.Cut(version, "-")
|
||||
// also trim "~..." suffix used historically (https://gitlab.com/apparmor/apparmor/-/commit/bca67d3d27d219d11ce8c9cc70612bd637f88c10)
|
||||
version = strings.SplitN(version, "~", 2)[0]
|
||||
version, _, _ = strings.Cut(version, "~")
|
||||
|
||||
// split by major minor version
|
||||
v := strings.Split(version, ".")
|
||||
|
||||
3
vendor/go.podman.io/common/pkg/auth/auth.go
generated
vendored
3
vendor/go.podman.io/common/pkg/auth/auth.go
generated
vendored
@@ -233,8 +233,7 @@ func parseCredentialsKey(arg string, acceptRepositories bool) (key, registry str
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
split := strings.Split(key, "/")
|
||||
registry = split[0]
|
||||
registry, _, _ = strings.Cut(key, "/")
|
||||
|
||||
if !acceptRepositories {
|
||||
return registry, registry, nil
|
||||
|
||||
19
vendor/go.podman.io/common/pkg/cgroups/cgroups_linux.go
generated
vendored
19
vendor/go.podman.io/common/pkg/cgroups/cgroups_linux.go
generated
vendored
@@ -111,7 +111,7 @@ func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed while reading controllers for cgroup v2: %w", err)
|
||||
}
|
||||
for _, controllerName := range strings.Fields(string(controllersFileBytes)) {
|
||||
for controllerName := range strings.FieldsSeq(string(controllersFileBytes)) {
|
||||
c := controller{
|
||||
name: controllerName,
|
||||
symlink: false,
|
||||
@@ -197,10 +197,9 @@ func getCgroupPathForCurrentProcess() (string, error) {
|
||||
s := bufio.NewScanner(f)
|
||||
for s.Scan() {
|
||||
text := s.Text()
|
||||
procEntries := strings.SplitN(text, "::", 2)
|
||||
// set process cgroupPath only if entry is valid
|
||||
if len(procEntries) > 1 {
|
||||
cgroupPath = procEntries[1]
|
||||
if _, p, ok := strings.Cut(text, "::"); ok {
|
||||
cgroupPath = p
|
||||
}
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
@@ -278,10 +277,10 @@ func readFileByKeyAsUint64(path, key string) (uint64, error) {
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for _, line := range strings.Split(string(content), "\n") {
|
||||
fields := strings.SplitN(line, " ", 2)
|
||||
if fields[0] == key {
|
||||
v := cleanString(fields[1])
|
||||
for line := range strings.SplitSeq(string(content), "\n") {
|
||||
k, v, _ := strings.Cut(line, " ")
|
||||
if k == key {
|
||||
v := cleanString(v)
|
||||
if v == "max" {
|
||||
return math.MaxUint64, nil
|
||||
}
|
||||
@@ -684,7 +683,7 @@ func readAcctList(ctr *CgroupControl, name string) ([]uint64, error) {
|
||||
return nil, err
|
||||
}
|
||||
r := []uint64{}
|
||||
for _, s := range strings.Split(string(data), " ") {
|
||||
for s := range strings.SplitSeq(string(data), " ") {
|
||||
s = cleanString(s)
|
||||
if s == "" {
|
||||
break
|
||||
@@ -874,7 +873,7 @@ func rmDirRecursively(path string) error {
|
||||
}
|
||||
// kill all the processes that are still part of the cgroup
|
||||
if procs, err := os.ReadFile(filepath.Join(path, "cgroup.procs")); err == nil {
|
||||
for _, pidS := range strings.Split(string(procs), "\n") {
|
||||
for pidS := range strings.SplitSeq(string(procs), "\n") {
|
||||
if pid, err := strconv.Atoi(pidS); err == nil {
|
||||
_ = unix.Kill(pid, signal)
|
||||
}
|
||||
|
||||
8
vendor/go.podman.io/common/pkg/cgroups/cgroups_unsupported.go
generated
vendored
8
vendor/go.podman.io/common/pkg/cgroups/cgroups_unsupported.go
generated
vendored
@@ -2,10 +2,6 @@
|
||||
|
||||
package cgroups
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 cgroup2 mode.
|
||||
func IsCgroup2UnifiedMode() (bool, error) {
|
||||
return false, nil
|
||||
@@ -16,7 +12,3 @@ func IsCgroup2UnifiedMode() (bool, error) {
|
||||
func UserOwnsCurrentSystemdCgroup() (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func rmDirRecursively(path string) error {
|
||||
return os.RemoveAll(path)
|
||||
}
|
||||
|
||||
2
vendor/go.podman.io/common/pkg/cgroups/systemd_linux.go
generated
vendored
2
vendor/go.podman.io/common/pkg/cgroups/systemd_linux.go
generated
vendored
@@ -280,7 +280,7 @@ func resourcesToProps(res *cgroups.Resources, v2 bool) (map[string]uint64, map[s
|
||||
func rangeToBits(str string) ([]byte, error) {
|
||||
bits := new(big.Int)
|
||||
|
||||
for _, r := range strings.Split(str, ",") {
|
||||
for r := range strings.SplitSeq(str, ",") {
|
||||
// allow extra spaces around
|
||||
r = strings.TrimSpace(r)
|
||||
// allow empty elements (extra commas)
|
||||
|
||||
2
vendor/go.podman.io/common/pkg/cgroups/utils_linux.go
generated
vendored
2
vendor/go.podman.io/common/pkg/cgroups/utils_linux.go
generated
vendored
@@ -270,7 +270,7 @@ func MoveUnderCgroup(cgroup, subtree string, processes []uint32) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, pid := range bytes.Split(processesData, []byte("\n")) {
|
||||
for pid := range bytes.SplitSeq(processesData, []byte("\n")) {
|
||||
if len(pid) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
2
vendor/go.podman.io/common/pkg/cgroupv2/cgroups_unsupported.go
generated
vendored
2
vendor/go.podman.io/common/pkg/cgroupv2/cgroups_unsupported.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
|
||||
package cgroupv2
|
||||
|
||||
// Enabled returns whether we are running on cgroup v2
|
||||
// Enabled returns whether we are running on cgroup v2.
|
||||
func Enabled() (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
2
vendor/go.podman.io/common/pkg/completion/completion.go
generated
vendored
2
vendor/go.podman.io/common/pkg/completion/completion.go
generated
vendored
@@ -72,7 +72,7 @@ func autocompleteSubIDName(filename string) ([]string, cobra.ShellCompDirective)
|
||||
var names []string
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
name := strings.SplitN(scanner.Text(), ":", 2)[0]
|
||||
name, _, _ := strings.Cut(scanner.Text(), ":")
|
||||
names = append(names, name)
|
||||
}
|
||||
if err = scanner.Err(); err != nil {
|
||||
|
||||
25
vendor/go.podman.io/common/pkg/config/config.go
generated
vendored
25
vendor/go.podman.io/common/pkg/config/config.go
generated
vendored
@@ -707,6 +707,13 @@ type Destination struct {
|
||||
// Identity file with ssh key, optional
|
||||
Identity string `json:",omitempty" toml:"identity,omitempty"`
|
||||
|
||||
// Path to TLS client certificate PEM file, optional
|
||||
TLSCert string `json:",omitempty" toml:"tls_cert,omitempty"`
|
||||
// Path to TLS client certificate private key PEM file, optional
|
||||
TLSKey string `json:",omitempty" toml:"tls_key,omitempty"`
|
||||
// Path to TLS certificate authority PEM file, optional
|
||||
TLSCA string `json:",omitempty" toml:"tls_ca,omitempty"`
|
||||
|
||||
// isMachine describes if the remote destination is a machine.
|
||||
IsMachine bool `json:",omitempty" toml:"is_machine,omitempty"`
|
||||
}
|
||||
@@ -761,9 +768,9 @@ func (c *Config) CheckCgroupsAndAdjustConfig() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, part := range strings.Split(session, ",") {
|
||||
if strings.HasPrefix(part, "unix:path=") {
|
||||
err := fileutils.Exists(strings.TrimPrefix(part, "unix:path="))
|
||||
for part := range strings.SplitSeq(session, ",") {
|
||||
if path, ok := strings.CutPrefix(part, "unix:path="); ok {
|
||||
err := fileutils.Exists(path)
|
||||
hasSession = err == nil
|
||||
break
|
||||
}
|
||||
@@ -1158,17 +1165,17 @@ func (c *Config) ImageCopyTmpDir() (string, error) {
|
||||
// setupEnv sets the environment variables for the engine.
|
||||
func (c *Config) setupEnv() error {
|
||||
for _, env := range c.Engine.Env.Get() {
|
||||
splitEnv := strings.SplitN(env, "=", 2)
|
||||
if len(splitEnv) != 2 {
|
||||
key, value, ok := strings.Cut(env, "=")
|
||||
if !ok {
|
||||
logrus.Warnf("invalid environment variable for engine %s, valid configuration is KEY=value pair", env)
|
||||
continue
|
||||
}
|
||||
// skip if the env is already defined
|
||||
if _, ok := os.LookupEnv(splitEnv[0]); ok {
|
||||
logrus.Debugf("environment variable %s is already defined, skip the settings from containers.conf", splitEnv[0])
|
||||
if _, ok := os.LookupEnv(key); ok {
|
||||
logrus.Debugf("environment variable %s is already defined, skip the settings from containers.conf", key)
|
||||
continue
|
||||
}
|
||||
if err := os.Setenv(splitEnv[0], splitEnv[1]); err != nil {
|
||||
if err := os.Setenv(key, value); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -1202,7 +1209,7 @@ func (e eventsLogMaxSize) MarshalText() ([]byte, error) {
|
||||
v := []byte{}
|
||||
return v, nil
|
||||
}
|
||||
return []byte(fmt.Sprintf("%d", e)), nil
|
||||
return fmt.Appendf(nil, "%d", e), nil
|
||||
}
|
||||
|
||||
func ValidateImageVolumeMode(mode string) error {
|
||||
|
||||
2
vendor/go.podman.io/common/pkg/config/config_unsupported.go
generated
vendored
2
vendor/go.podman.io/common/pkg/config/config_unsupported.go
generated
vendored
@@ -7,7 +7,7 @@ func selinuxEnabled() bool {
|
||||
}
|
||||
|
||||
// Capabilities returns the capabilities parses the Add and Drop capability
|
||||
// list from the default capabilities for the container
|
||||
// list from the default capabilities for the container.
|
||||
func (c *Config) Capabilities(user string, addCapabilities, dropCapabilities []string) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
17
vendor/go.podman.io/common/pkg/config/containers.conf
generated
vendored
17
vendor/go.podman.io/common/pkg/config/containers.conf
generated
vendored
@@ -317,11 +317,13 @@ default_sysctls = [
|
||||
#
|
||||
#umask = "0022"
|
||||
|
||||
# Default way to to create a User namespace for the container
|
||||
# Default way to create a USER namespace for the container.
|
||||
# Options are:
|
||||
# `auto` Create unique User Namespace for the container.
|
||||
# `host` Share host User Namespace with the container.
|
||||
#
|
||||
# `private` Create private USER Namespace for the container, without adding any UID mappings.
|
||||
# `host` Share host USER Namespace with the container. Root in the container is mapped to the host user UID.
|
||||
# `auto` Automatically create a USER namespace with a unique mapping.
|
||||
# `keep-id` Like `private`, but container UIDs are mapped to the host user's subordinate UIDs listed in `/etc/subuid`, and the current user's `UID:GID` are mapped to the same values in the container.
|
||||
# `no-map` Like `keep-id`, but the current user's `UID:GID` does not map to any `UID:GID` inside the container.
|
||||
#userns = "host"
|
||||
|
||||
# Default way to to create a UTS namespace for the container
|
||||
@@ -777,10 +779,17 @@ default_sysctls = [
|
||||
# rootful "unix:///run/podman/podman.sock (Default)
|
||||
# remote rootless ssh://engineering.lab.company.com/run/user/1000/podman/podman.sock
|
||||
# remote rootful ssh://root@10.10.1.136:22/run/podman/podman.sock
|
||||
# tcp/tls remote tcp://10.10.1.136:9443
|
||||
#
|
||||
# uri = "ssh://user@production.example.com/run/user/1001/podman/podman.sock"
|
||||
# Path to file containing ssh identity key
|
||||
# identity = "~/.ssh/id_rsa"
|
||||
# Path to PEM file containing TLS client certificate
|
||||
# tls_cert = "/path/to/certs/podman/tls.crt"
|
||||
# Path to PEM file containing TLS client certificate private key
|
||||
# tls_key = "/path/to/certs/podman/tls.key"
|
||||
# Path to PEM file containing TLS certificate authority (CA) bundle
|
||||
# tls_ca = "/path/to/certs/podman/ca.crt"
|
||||
|
||||
# Directory for temporary files. Must be tmpfs (wiped after reboot)
|
||||
#
|
||||
|
||||
7
vendor/go.podman.io/common/pkg/config/containers.conf-freebsd
generated
vendored
7
vendor/go.podman.io/common/pkg/config/containers.conf-freebsd
generated
vendored
@@ -598,10 +598,17 @@ default_sysctls = [
|
||||
# rootful "unix:///run/podman/podman.sock (Default)
|
||||
# remote rootless ssh://engineering.lab.company.com/run/user/1000/podman/podman.sock
|
||||
# remote rootful ssh://root@10.10.1.136:22/run/podman/podman.sock
|
||||
# tcp/tls remote tcp://10.10.1.136:9443
|
||||
#
|
||||
# uri = "ssh://user@production.example.com/run/user/1001/podman/podman.sock"
|
||||
# Path to file containing ssh identity key
|
||||
# identity = "~/.ssh/id_rsa"
|
||||
# Path to PEM file containing TLS client certificate
|
||||
# tls_cert = "/path/to/certs/podman/tls.crt"
|
||||
# Path to PEM file containing TLS client certificate private key
|
||||
# tls_key = "/path/to/certs/podman/tls.key"
|
||||
# Path to PEM file containing TLS certificate authority (CA) bundle
|
||||
# tls_ca = "/path/to/certs/podman/ca.crt"
|
||||
|
||||
# Directory for temporary files. Must be tmpfs (wiped after reboot)
|
||||
#
|
||||
|
||||
10
vendor/go.podman.io/common/pkg/config/default.go
generated
vendored
10
vendor/go.podman.io/common/pkg/config/default.go
generated
vendored
@@ -145,16 +145,6 @@ var (
|
||||
// helper binary in a different location.
|
||||
additionalHelperBinariesDir string
|
||||
|
||||
defaultUnixComposeProviders = []string{
|
||||
"$HOME/.docker/cli-plugins/docker-compose",
|
||||
"/usr/local/lib/docker/cli-plugins/docker-compose",
|
||||
"/usr/local/libexec/docker/cli-plugins/docker-compose",
|
||||
"/usr/lib/docker/cli-plugins/docker-compose",
|
||||
"/usr/libexec/docker/cli-plugins/docker-compose",
|
||||
"docker-compose",
|
||||
"podman-compose",
|
||||
}
|
||||
|
||||
defaultContainerEnv = []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}
|
||||
)
|
||||
|
||||
|
||||
4
vendor/go.podman.io/common/pkg/config/default_bsd.go
generated
vendored
4
vendor/go.podman.io/common/pkg/config/default_bsd.go
generated
vendored
@@ -28,7 +28,3 @@ func getLibpodTmpDir() string {
|
||||
func getDefaultMachineVolumes() []string {
|
||||
return []string{"$HOME:$HOME"}
|
||||
}
|
||||
|
||||
func getDefaultComposeProviders() []string {
|
||||
return defaultUnixComposeProviders
|
||||
}
|
||||
|
||||
2
vendor/go.podman.io/common/pkg/config/default_darwin.go
generated
vendored
2
vendor/go.podman.io/common/pkg/config/default_darwin.go
generated
vendored
@@ -12,7 +12,7 @@ func getLibpodTmpDir() string {
|
||||
return "/run/libpod"
|
||||
}
|
||||
|
||||
// getDefaultMachineVolumes returns default mounted volumes (possibly with env vars, which will be expanded)
|
||||
// getDefaultMachineVolumes returns default mounted volumes (possibly with env vars, which will be expanded).
|
||||
func getDefaultMachineVolumes() []string {
|
||||
return []string{
|
||||
"/Users:/Users",
|
||||
|
||||
4
vendor/go.podman.io/common/pkg/config/default_linux.go
generated
vendored
4
vendor/go.podman.io/common/pkg/config/default_linux.go
generated
vendored
@@ -29,7 +29,3 @@ func getLibpodTmpDir() string {
|
||||
func getDefaultMachineVolumes() []string {
|
||||
return []string{"$HOME:$HOME"}
|
||||
}
|
||||
|
||||
func getDefaultComposeProviders() []string {
|
||||
return defaultUnixComposeProviders
|
||||
}
|
||||
|
||||
17
vendor/go.podman.io/common/pkg/config/default_unix_notdarwin.go
generated
vendored
Normal file
17
vendor/go.podman.io/common/pkg/config/default_unix_notdarwin.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
//go:build linux || freebsd || netbsd || openbsd
|
||||
|
||||
package config
|
||||
|
||||
var defaultUnixComposeProviders = []string{
|
||||
"$HOME/.docker/cli-plugins/docker-compose",
|
||||
"/usr/local/lib/docker/cli-plugins/docker-compose",
|
||||
"/usr/local/libexec/docker/cli-plugins/docker-compose",
|
||||
"/usr/lib/docker/cli-plugins/docker-compose",
|
||||
"/usr/libexec/docker/cli-plugins/docker-compose",
|
||||
"docker-compose",
|
||||
"podman-compose",
|
||||
}
|
||||
|
||||
func getDefaultComposeProviders() []string {
|
||||
return defaultUnixComposeProviders
|
||||
}
|
||||
12
vendor/go.podman.io/common/pkg/config/default_unsupported.go
generated
vendored
12
vendor/go.podman.io/common/pkg/config/default_unsupported.go
generated
vendored
@@ -4,17 +4,7 @@ package config
|
||||
|
||||
import "os"
|
||||
|
||||
// isCgroup2UnifiedMode returns whether we are running in cgroup2 mode.
|
||||
func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// getDefaultProcessLimits returns the nofile and nproc for the current process in ulimits format
|
||||
func getDefaultProcessLimits() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// getDefaultTmpDir for linux
|
||||
// getDefaultTmpDir for linux.
|
||||
func getDefaultTmpDir() string {
|
||||
// first check the TMPDIR env var
|
||||
if path, found := os.LookupEnv("TMPDIR"); found {
|
||||
|
||||
10
vendor/go.podman.io/common/pkg/config/default_windows.go
generated
vendored
10
vendor/go.podman.io/common/pkg/config/default_windows.go
generated
vendored
@@ -9,16 +9,6 @@ import (
|
||||
"go.podman.io/storage/pkg/homedir"
|
||||
)
|
||||
|
||||
// isCgroup2UnifiedMode returns whether we are running in cgroup2 mode.
|
||||
func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// getDefaultProcessLimits returns the nofile and nproc for the current process in ulimits format
|
||||
func getDefaultProcessLimits() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// getDefaultTmpDir for windows
|
||||
func getDefaultTmpDir() string {
|
||||
// first check the Temp env var
|
||||
|
||||
13
vendor/go.podman.io/common/pkg/config/systemd.go
generated
vendored
13
vendor/go.podman.io/common/pkg/config/systemd.go
generated
vendored
@@ -5,16 +5,14 @@ package config
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"go.podman.io/common/pkg/cgroupv2"
|
||||
"go.podman.io/common/pkg/systemd"
|
||||
"go.podman.io/storage/pkg/unshare"
|
||||
)
|
||||
|
||||
var (
|
||||
systemdOnce sync.Once
|
||||
usesSystemd bool
|
||||
journaldOnce sync.Once
|
||||
usesJournald bool
|
||||
)
|
||||
@@ -51,14 +49,7 @@ func defaultLogDriver() string {
|
||||
}
|
||||
|
||||
func useSystemd() bool {
|
||||
systemdOnce.Do(func() {
|
||||
dat, err := os.ReadFile("/proc/1/comm")
|
||||
if err == nil {
|
||||
val := strings.TrimSuffix(string(dat), "\n")
|
||||
usesSystemd = (val == "systemd")
|
||||
}
|
||||
})
|
||||
return usesSystemd
|
||||
return systemd.RunsOnSystemd()
|
||||
}
|
||||
|
||||
func useJournald() bool {
|
||||
|
||||
9
vendor/go.podman.io/common/pkg/manifests/manifests.go
generated
vendored
9
vendor/go.podman.io/common/pkg/manifests/manifests.go
generated
vendored
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
@@ -238,9 +239,7 @@ func (l *list) SetAnnotations(instanceDigest *digest.Digest, annotations map[str
|
||||
if *a == nil {
|
||||
(*a) = make(map[string]string)
|
||||
}
|
||||
for k, v := range annotations {
|
||||
(*a)[k] = v
|
||||
}
|
||||
maps.Copy((*a), annotations)
|
||||
if len(*a) == 0 {
|
||||
*a = nil
|
||||
}
|
||||
@@ -259,9 +258,7 @@ func (l *list) Annotations(instanceDigest *digest.Digest) (map[string]string, er
|
||||
a = oci.Annotations
|
||||
}
|
||||
annotations := make(map[string]string)
|
||||
for k, v := range a {
|
||||
annotations[k] = v
|
||||
}
|
||||
maps.Copy(annotations, a)
|
||||
return annotations, nil
|
||||
}
|
||||
|
||||
|
||||
9
vendor/go.podman.io/common/pkg/report/formatter.go
generated
vendored
9
vendor/go.podman.io/common/pkg/report/formatter.go
generated
vendored
@@ -2,6 +2,7 @@ package report
|
||||
|
||||
import (
|
||||
"io"
|
||||
"maps"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
@@ -109,12 +110,8 @@ func (f *Formatter) Parse(origin Origin, text string) (*Formatter, error) {
|
||||
// A default template function will be replaced if there is a key collision.
|
||||
func (f *Formatter) Funcs(funcMap template.FuncMap) *Formatter {
|
||||
m := make(template.FuncMap, len(DefaultFuncs)+len(funcMap))
|
||||
for k, v := range DefaultFuncs {
|
||||
m[k] = v
|
||||
}
|
||||
for k, v := range funcMap {
|
||||
m[k] = v
|
||||
}
|
||||
maps.Copy(m, DefaultFuncs)
|
||||
maps.Copy(m, funcMap)
|
||||
f.template = f.template.Funcs(funcMap)
|
||||
return f
|
||||
}
|
||||
|
||||
15
vendor/go.podman.io/common/pkg/report/template.go
generated
vendored
15
vendor/go.podman.io/common/pkg/report/template.go
generated
vendored
@@ -3,6 +3,7 @@ package report
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"maps"
|
||||
"reflect"
|
||||
"strings"
|
||||
"text/template"
|
||||
@@ -95,7 +96,7 @@ func truncateWithLength(source string, length int) string {
|
||||
// 3) --format 'table {{.ID}}' # includes headers
|
||||
func Headers(object any, overrides map[string]string) []map[string]string {
|
||||
value := reflect.ValueOf(object)
|
||||
if value.Kind() == reflect.Ptr {
|
||||
if value.Kind() == reflect.Pointer {
|
||||
value = value.Elem()
|
||||
}
|
||||
|
||||
@@ -106,9 +107,7 @@ func Headers(object any, overrides map[string]string) []map[string]string {
|
||||
// Recurse to find field names from promoted structs
|
||||
if field.Type.Kind() == reflect.Struct && field.Anonymous {
|
||||
h := Headers(reflect.New(field.Type).Interface(), nil)
|
||||
for k, v := range h[0] {
|
||||
headers[k] = v
|
||||
}
|
||||
maps.Copy(headers, h[0])
|
||||
continue
|
||||
}
|
||||
name := strings.Join(camelcase.Split(field.Name), " ")
|
||||
@@ -146,12 +145,8 @@ func (t *Template) Parse(text string) (*Template, error) {
|
||||
// A default template function will be replace if there is a key collision.
|
||||
func (t *Template) Funcs(funcMap FuncMap) *Template {
|
||||
m := make(FuncMap)
|
||||
for k, v := range DefaultFuncs {
|
||||
m[k] = v
|
||||
}
|
||||
for k, v := range funcMap {
|
||||
m[k] = v
|
||||
}
|
||||
maps.Copy(m, DefaultFuncs)
|
||||
maps.Copy(m, funcMap)
|
||||
return &Template{Template: t.Template.Funcs(template.FuncMap(m)), isTable: t.isTable}
|
||||
}
|
||||
|
||||
|
||||
6
vendor/go.podman.io/common/pkg/seccomp/seccomp_unsupported.go
generated
vendored
6
vendor/go.podman.io/common/pkg/seccomp/seccomp_unsupported.go
generated
vendored
@@ -14,12 +14,12 @@ import (
|
||||
|
||||
var errNotSupported = errors.New("seccomp not enabled in this build")
|
||||
|
||||
// LoadProfile returns an error on unsupported systems
|
||||
// LoadProfile returns an error on unsupported systems.
|
||||
func LoadProfile(body string, rs *specs.Spec) (*specs.LinuxSeccomp, error) {
|
||||
return nil, errNotSupported
|
||||
}
|
||||
|
||||
// GetDefaultProfile returns an error on unsupported systems
|
||||
// GetDefaultProfile returns an error on unsupported systems.
|
||||
func GetDefaultProfile(rs *specs.Spec) (*specs.LinuxSeccomp, error) {
|
||||
return nil, errNotSupported
|
||||
}
|
||||
@@ -29,7 +29,7 @@ func LoadProfileFromBytes(body []byte, rs *specs.Spec) (*specs.LinuxSeccomp, err
|
||||
return nil, errNotSupported
|
||||
}
|
||||
|
||||
// LoadProfileFromConfig takes a Seccomp struct and a spec to retrieve a LinuxSeccomp
|
||||
// LoadProfileFromConfig takes a Seccomp struct and a spec to retrieve a LinuxSeccomp.
|
||||
func LoadProfileFromConfig(config *Seccomp, specgen *specs.Spec) (*specs.LinuxSeccomp, error) {
|
||||
return nil, errNotSupported
|
||||
}
|
||||
|
||||
3
vendor/go.podman.io/common/pkg/secrets/shelldriver/shelldriver.go
generated
vendored
3
vendor/go.podman.io/common/pkg/secrets/shelldriver/shelldriver.go
generated
vendored
@@ -89,8 +89,7 @@ func (d *Driver) List() (secrets []string, err error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parts := bytes.Split(buf.Bytes(), []byte("\n"))
|
||||
for _, part := range parts {
|
||||
for part := range bytes.SplitSeq(buf.Bytes(), []byte("\n")) {
|
||||
id := strings.Trim(string(part), " \r\n")
|
||||
if len(id) > 0 {
|
||||
secrets = append(secrets, id)
|
||||
|
||||
3
vendor/go.podman.io/common/pkg/ssh/connection_golang.go
generated
vendored
3
vendor/go.podman.io/common/pkg/ssh/connection_golang.go
generated
vendored
@@ -166,8 +166,7 @@ func golangConnectionScp(options ConnectionScpOptions) (*ConnectionScpReport, er
|
||||
|
||||
parent := filepath.Dir(remoteFile)
|
||||
path := string(filepath.Separator)
|
||||
dirs := strings.Split(parent, path)
|
||||
for _, dir := range dirs {
|
||||
for dir := range strings.SplitSeq(parent, path) {
|
||||
path = filepath.Join(path, dir)
|
||||
// ignore errors due to most of the dirs already existing
|
||||
_ = sc.Mkdir(path)
|
||||
|
||||
8
vendor/go.podman.io/common/pkg/ssh/connection_native.go
generated
vendored
8
vendor/go.podman.io/common/pkg/ssh/connection_native.go
generated
vendored
@@ -38,8 +38,8 @@ func nativeConnectionCreate(options ConnectionCreateOptions) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.Contains(uri.Host, "/run") {
|
||||
uri.Host = strings.Split(uri.Host, "/run")[0]
|
||||
if host, _, ok := strings.Cut(uri.Host, "/run"); ok {
|
||||
uri.Host = host
|
||||
}
|
||||
conf, err := config.Default()
|
||||
if err != nil {
|
||||
@@ -114,8 +114,8 @@ func nativeConnectionExec(options ConnectionExecOptions, input io.Reader) (*Conn
|
||||
|
||||
output := &bytes.Buffer{}
|
||||
errors := &bytes.Buffer{}
|
||||
if strings.Contains(uri.Host, "/run") {
|
||||
uri.Host = strings.Split(uri.Host, "/run")[0]
|
||||
if host, _, ok := strings.Cut(uri.Host, "/run"); ok {
|
||||
uri.Host = host
|
||||
}
|
||||
|
||||
options.Args = append([]string{uri.User.String() + "@" + uri.Hostname()}, options.Args...)
|
||||
|
||||
18
vendor/go.podman.io/common/pkg/subscriptions/subscriptions.go
generated
vendored
18
vendor/go.podman.io/common/pkg/subscriptions/subscriptions.go
generated
vendored
@@ -144,15 +144,12 @@ func getMounts(filePath string) []string {
|
||||
}
|
||||
|
||||
// getHostAndCtrDir separates the host:container paths.
|
||||
func getMountsMap(path string) (string, string, error) { //nolint
|
||||
arr := strings.SplitN(path, ":", 2)
|
||||
switch len(arr) {
|
||||
case 1:
|
||||
return arr[0], arr[0], nil
|
||||
case 2:
|
||||
return arr[0], arr[1], nil
|
||||
func getMountsMap(path string) (string, string) {
|
||||
host, ctr, ok := strings.Cut(path, ":")
|
||||
if !ok {
|
||||
return path, path
|
||||
}
|
||||
return "", "", fmt.Errorf("unable to get host and container dir from path: %s", path)
|
||||
return host, ctr
|
||||
}
|
||||
|
||||
// Return true iff the system is in FIPS mode as determined by reading
|
||||
@@ -238,10 +235,7 @@ func addSubscriptionsFromMountsFile(filePath, mountLabel, containerRunDir string
|
||||
defaultMountsPaths := getMounts(filePath)
|
||||
mounts := make([]rspec.Mount, 0, len(defaultMountsPaths))
|
||||
for _, path := range defaultMountsPaths {
|
||||
hostDirOrFile, ctrDirOrFile, err := getMountsMap(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hostDirOrFile, ctrDirOrFile := getMountsMap(path)
|
||||
// skip if the hostDirOrFile path doesn't exist
|
||||
fileInfo, err := os.Stat(hostDirOrFile)
|
||||
if err != nil {
|
||||
|
||||
10
vendor/go.podman.io/common/pkg/timetype/timestamp.go
generated
vendored
10
vendor/go.podman.io/common/pkg/timetype/timestamp.go
generated
vendored
@@ -117,19 +117,19 @@ func ParseTimestamps(value string, def int64) (secs, nanoSecs int64, err error)
|
||||
}
|
||||
|
||||
func parseTimestamp(value string) (int64, int64, error) {
|
||||
sa := strings.SplitN(value, ".", 2)
|
||||
s, err := strconv.ParseInt(sa[0], 10, 64)
|
||||
secStr, nsStr, ok := strings.Cut(value, ".")
|
||||
s, err := strconv.ParseInt(secStr, 10, 64)
|
||||
if err != nil {
|
||||
return s, 0, err
|
||||
}
|
||||
if len(sa) != 2 {
|
||||
if !ok {
|
||||
return s, 0, nil
|
||||
}
|
||||
n, err := strconv.ParseInt(sa[1], 10, 64)
|
||||
n, err := strconv.ParseInt(nsStr, 10, 64)
|
||||
if err != nil {
|
||||
return s, n, err
|
||||
}
|
||||
// should already be in nanoseconds but just in case convert n to nanoseconds
|
||||
n = int64(float64(n) * math.Pow(float64(10), float64(9-len(sa[1]))))
|
||||
n = int64(float64(n) * math.Pow(float64(10), float64(9-len(nsStr))))
|
||||
return s, n, nil
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user