mirror of https://github.com/containers/podman.git
Enhance system connection add URL input
* Add support for the tcp and unix schemes in connection URLs. Signed-off-by: Jhon Honce <jhonce@redhat.com>
This commit is contained in:
parent
1846070f05
commit
2ce78aace6
|
@ -23,22 +23,24 @@ import (
|
||||||
"golang.org/x/crypto/ssh/agent"
|
"golang.org/x/crypto/ssh/agent"
|
||||||
)
|
)
|
||||||
|
|
||||||
const schemaPattern = "^[A-Za-z][A-Za-z0-9+.-]*:"
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
addCmd = &cobra.Command{
|
addCmd = &cobra.Command{
|
||||||
Use: "add [options] NAME DESTINATION",
|
Use: "add [options] NAME DESTINATION",
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
Short: "Record destination for the Podman service",
|
Short: "Record destination for the Podman service",
|
||||||
Long: `Add destination to podman configuration.
|
Long: `Add destination to podman configuration.
|
||||||
"destination" is of the form [user@]hostname or
|
"destination" is one of the form:
|
||||||
an URI of the form ssh://[user@]hostname[:port]
|
[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)
|
||||||
|
unix://path (absolute path required)
|
||||||
`,
|
`,
|
||||||
RunE: add,
|
RunE: add,
|
||||||
ValidArgsFunction: completion.AutocompleteNone,
|
ValidArgsFunction: completion.AutocompleteNone,
|
||||||
Example: `podman system connection add laptop server.fubar.com
|
Example: `podman system connection add laptop server.fubar.com
|
||||||
podman system connection add --identity ~/.ssh/dev_rsa testing ssh://root@server.fubar.com:2222
|
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 --identity ~/.ssh/dev_rsa --port 22 production root@server.fubar.com
|
||||||
|
podman system connection add debug tcp://localhost:8080
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,9 +76,9 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func add(cmd *cobra.Command, args []string) error {
|
func add(cmd *cobra.Command, args []string) error {
|
||||||
// Default to ssh: schema if none given
|
// Default to ssh schema if none given
|
||||||
dest := args[1]
|
dest := args[1]
|
||||||
if match, err := regexp.Match(schemaPattern, []byte(dest)); err != nil {
|
if match, err := regexp.Match("^[A-Za-z][A-Za-z0-9+.-]*://", []byte(dest)); err != nil {
|
||||||
return errors.Wrapf(err, "invalid destination")
|
return errors.Wrapf(err, "invalid destination")
|
||||||
} else if !match {
|
} else if !match {
|
||||||
dest = "ssh://" + dest
|
dest = "ssh://" + dest
|
||||||
|
@ -87,16 +89,18 @@ func add(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cmd.Flags().Changed("socket-path") {
|
||||||
|
uri.Path = cmd.Flag("socket-path").Value.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch uri.Scheme {
|
||||||
|
case "ssh":
|
||||||
if uri.User.Username() == "" {
|
if uri.User.Username() == "" {
|
||||||
if uri.User, err = getUserInfo(uri); err != nil {
|
if uri.User, err = getUserInfo(uri); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.Flags().Changed("socket-path") {
|
|
||||||
uri.Path = cmd.Flag("socket-path").Value.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
if cmd.Flags().Changed("port") {
|
if cmd.Flags().Changed("port") {
|
||||||
uri.Host = net.JoinHostPort(uri.Hostname(), cmd.Flag("port").Value.String())
|
uri.Host = net.JoinHostPort(uri.Hostname(), cmd.Flag("port").Value.String())
|
||||||
}
|
}
|
||||||
|
@ -110,6 +114,39 @@ func add(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "unix":
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := os.Stat(uri.Path)
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, os.ErrNotExist):
|
||||||
|
logrus.Warnf("%q does not exists", uri.Path)
|
||||||
|
case errors.Is(err, os.ErrPermission):
|
||||||
|
logrus.Warnf("You do not have permission to read %q", uri.Path)
|
||||||
|
case err != nil:
|
||||||
|
return err
|
||||||
|
case info.Mode()&os.ModeSocket == 0:
|
||||||
|
return fmt.Errorf("%q exists and is not a unix domain socket", uri.Path)
|
||||||
|
}
|
||||||
|
case "tcp":
|
||||||
|
if cmd.Flags().Changed("socket-path") {
|
||||||
|
return errors.New("--socket-path option not supported for tcp scheme")
|
||||||
|
}
|
||||||
|
if cmd.Flags().Changed("identity") {
|
||||||
|
return errors.New("--identity option not supported for tcp scheme")
|
||||||
|
}
|
||||||
|
if uri.Port() == "" {
|
||||||
|
return errors.New("tcp scheme requires a port either via --port or in destination URL")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
logrus.Warnf("%q unknown scheme, no validation provided", uri.Scheme)
|
||||||
|
}
|
||||||
|
|
||||||
cfg, err := config.ReadCustomConfig()
|
cfg, err := config.ReadCustomConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -10,6 +10,8 @@ podman\-system\-connection\-add - Record destination for the Podman service
|
||||||
Record ssh destination for remote podman service(s). The ssh destination is given as one of:
|
Record ssh destination for remote podman service(s). The ssh destination is given as one of:
|
||||||
- [user@]hostname[:port]
|
- [user@]hostname[:port]
|
||||||
- ssh://[user@]hostname[:port]
|
- ssh://[user@]hostname[:port]
|
||||||
|
- unix://path
|
||||||
|
- tcp://hostname:port
|
||||||
|
|
||||||
The user will be prompted for the remote ssh login password or key file pass phrase as required. The `ssh-agent` is supported if it is running.
|
The user will be prompted for the remote ssh login password or key file pass phrase as required. The `ssh-agent` is supported if it is running.
|
||||||
|
|
||||||
|
@ -38,6 +40,10 @@ Path to the Podman service unix domain socket on the ssh destination host
|
||||||
$ podman system connection add QA podman.example.com
|
$ podman system connection add QA podman.example.com
|
||||||
|
|
||||||
$ podman system connection add --identity ~/.ssh/dev_rsa production ssh://root@server.example.com:2222
|
$ podman system connection add --identity ~/.ssh/dev_rsa production ssh://root@server.example.com:2222
|
||||||
|
|
||||||
|
$ podman system connection add unix:///run/podman/podman.sock
|
||||||
|
|
||||||
|
$ podman system connection add tcp://localhost:8080
|
||||||
```
|
```
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
podman-system(1) , podman-system-connection(1) , containers.conf(5)
|
podman-system(1) , podman-system-connection(1) , containers.conf(5)
|
||||||
|
|
|
@ -53,7 +53,7 @@ var _ = Describe("podman system connection", func() {
|
||||||
GinkgoWriter.Write([]byte(timedResult))
|
GinkgoWriter.Write([]byte(timedResult))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("add", func() {
|
It("add ssh://", func() {
|
||||||
cmd := []string{"system", "connection", "add",
|
cmd := []string{"system", "connection", "add",
|
||||||
"--default",
|
"--default",
|
||||||
"--identity", "~/.ssh/id_rsa",
|
"--identity", "~/.ssh/id_rsa",
|
||||||
|
@ -94,6 +94,68 @@ var _ = Describe("podman system connection", func() {
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("add UDS", func() {
|
||||||
|
cmd := []string{"system", "connection", "add",
|
||||||
|
"QA-UDS",
|
||||||
|
"unix:///run/podman/podman.sock",
|
||||||
|
}
|
||||||
|
session := podmanTest.Podman(cmd)
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).Should(Exit(0))
|
||||||
|
Expect(session.Out).Should(Say(""))
|
||||||
|
|
||||||
|
cfg, err := config.ReadCustomConfig()
|
||||||
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
Expect(cfg.Engine.ActiveService).To(Equal("QA-UDS"))
|
||||||
|
Expect(cfg.Engine.ServiceDestinations["QA-UDS"]).To(Equal(
|
||||||
|
config.Destination{
|
||||||
|
URI: "unix:///run/podman/podman.sock",
|
||||||
|
Identity: "",
|
||||||
|
},
|
||||||
|
))
|
||||||
|
|
||||||
|
cmd = []string{"system", "connection", "add",
|
||||||
|
"QA-UDS1",
|
||||||
|
"--socket-path", "/run/user/podman/podman.sock",
|
||||||
|
"unix:///run/podman/podman.sock",
|
||||||
|
}
|
||||||
|
session = podmanTest.Podman(cmd)
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).Should(Exit(0))
|
||||||
|
Expect(session.Out).Should(Say(""))
|
||||||
|
|
||||||
|
cfg, err = config.ReadCustomConfig()
|
||||||
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
Expect(cfg.Engine.ActiveService).To(Equal("QA-UDS"))
|
||||||
|
Expect(cfg.Engine.ServiceDestinations["QA-UDS1"]).To(Equal(
|
||||||
|
config.Destination{
|
||||||
|
URI: "unix:///run/user/podman/podman.sock",
|
||||||
|
Identity: "",
|
||||||
|
},
|
||||||
|
))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("add tcp", func() {
|
||||||
|
cmd := []string{"system", "connection", "add",
|
||||||
|
"QA-TCP",
|
||||||
|
"tcp://localhost:8080",
|
||||||
|
}
|
||||||
|
session := podmanTest.Podman(cmd)
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).Should(Exit(0))
|
||||||
|
Expect(session.Out).Should(Say(""))
|
||||||
|
|
||||||
|
cfg, err := config.ReadCustomConfig()
|
||||||
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
Expect(cfg.Engine.ActiveService).To(Equal("QA-TCP"))
|
||||||
|
Expect(cfg.Engine.ServiceDestinations["QA-TCP"]).To(Equal(
|
||||||
|
config.Destination{
|
||||||
|
URI: "tcp://localhost:8080",
|
||||||
|
Identity: "",
|
||||||
|
},
|
||||||
|
))
|
||||||
|
})
|
||||||
|
|
||||||
It("remove", func() {
|
It("remove", func() {
|
||||||
cmd := []string{"system", "connection", "add",
|
cmd := []string{"system", "connection", "add",
|
||||||
"--default",
|
"--default",
|
||||||
|
|
Loading…
Reference in New Issue