Skip to content

Commit 4dc87c2

Browse files
Merge pull request containers#10821 from jwhonce/wip/connection
Enhance system connection add URL input
2 parents 1846070 + 2ce78aa commit 4dc87c2

File tree

3 files changed

+126
-21
lines changed

3 files changed

+126
-21
lines changed

cmd/podman/system/connection/add.go

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,24 @@ import (
2323
"golang.org/x/crypto/ssh/agent"
2424
)
2525

26-
const schemaPattern = "^[A-Za-z][A-Za-z0-9+.-]*:"
27-
2826
var (
2927
addCmd = &cobra.Command{
3028
Use: "add [options] NAME DESTINATION",
3129
Args: cobra.ExactArgs(2),
3230
Short: "Record destination for the Podman service",
3331
Long: `Add destination to podman configuration.
34-
"destination" is of the form [user@]hostname or
35-
an URI of the form ssh://[user@]hostname[:port]
32+
"destination" is one of the form:
33+
[user@]hostname (will default to ssh)
34+
ssh://[user@]hostname[:port][/path] (will obtain socket path from service, if not given.)
35+
tcp://hostname:port (not secured)
36+
unix://path (absolute path required)
3637
`,
3738
RunE: add,
3839
ValidArgsFunction: completion.AutocompleteNone,
3940
Example: `podman system connection add laptop server.fubar.com
4041
podman system connection add --identity ~/.ssh/dev_rsa testing ssh://[email protected]:2222
4142
podman system connection add --identity ~/.ssh/dev_rsa --port 22 production [email protected]
43+
podman system connection add debug tcp://localhost:8080
4244
`,
4345
}
4446

@@ -74,9 +76,9 @@ func init() {
7476
}
7577

7678
func add(cmd *cobra.Command, args []string) error {
77-
// Default to ssh: schema if none given
79+
// Default to ssh schema if none given
7880
dest := args[1]
79-
if match, err := regexp.Match(schemaPattern, []byte(dest)); err != nil {
81+
if match, err := regexp.Match("^[A-Za-z][A-Za-z0-9+.-]*://", []byte(dest)); err != nil {
8082
return errors.Wrapf(err, "invalid destination")
8183
} else if !match {
8284
dest = "ssh://" + dest
@@ -87,28 +89,63 @@ func add(cmd *cobra.Command, args []string) error {
8789
return err
8890
}
8991

90-
if uri.User.Username() == "" {
91-
if uri.User, err = getUserInfo(uri); err != nil {
92-
return err
93-
}
94-
}
95-
9692
if cmd.Flags().Changed("socket-path") {
9793
uri.Path = cmd.Flag("socket-path").Value.String()
9894
}
9995

100-
if cmd.Flags().Changed("port") {
101-
uri.Host = net.JoinHostPort(uri.Hostname(), cmd.Flag("port").Value.String())
102-
}
96+
switch uri.Scheme {
97+
case "ssh":
98+
if uri.User.Username() == "" {
99+
if uri.User, err = getUserInfo(uri); err != nil {
100+
return err
101+
}
102+
}
103103

104-
if uri.Port() == "" {
105-
uri.Host = net.JoinHostPort(uri.Hostname(), cmd.Flag("port").DefValue)
106-
}
104+
if cmd.Flags().Changed("port") {
105+
uri.Host = net.JoinHostPort(uri.Hostname(), cmd.Flag("port").Value.String())
106+
}
107107

108-
if uri.Path == "" || uri.Path == "/" {
109-
if uri.Path, err = getUDS(cmd, uri); err != nil {
108+
if uri.Port() == "" {
109+
uri.Host = net.JoinHostPort(uri.Hostname(), cmd.Flag("port").DefValue)
110+
}
111+
112+
if uri.Path == "" || uri.Path == "/" {
113+
if uri.Path, err = getUDS(cmd, uri); err != nil {
114+
return err
115+
}
116+
}
117+
case "unix":
118+
if cmd.Flags().Changed("identity") {
119+
return errors.New("--identity option not supported for unix scheme")
120+
}
121+
122+
if cmd.Flags().Changed("socket-path") {
123+
uri.Path = cmd.Flag("socket-path").Value.String()
124+
}
125+
126+
info, err := os.Stat(uri.Path)
127+
switch {
128+
case errors.Is(err, os.ErrNotExist):
129+
logrus.Warnf("%q does not exists", uri.Path)
130+
case errors.Is(err, os.ErrPermission):
131+
logrus.Warnf("You do not have permission to read %q", uri.Path)
132+
case err != nil:
110133
return err
134+
case info.Mode()&os.ModeSocket == 0:
135+
return fmt.Errorf("%q exists and is not a unix domain socket", uri.Path)
136+
}
137+
case "tcp":
138+
if cmd.Flags().Changed("socket-path") {
139+
return errors.New("--socket-path option not supported for tcp scheme")
140+
}
141+
if cmd.Flags().Changed("identity") {
142+
return errors.New("--identity option not supported for tcp scheme")
143+
}
144+
if uri.Port() == "" {
145+
return errors.New("tcp scheme requires a port either via --port or in destination URL")
111146
}
147+
default:
148+
logrus.Warnf("%q unknown scheme, no validation provided", uri.Scheme)
112149
}
113150

114151
cfg, err := config.ReadCustomConfig()

docs/source/markdown/podman-system-connection-add.1.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ podman\-system\-connection\-add - Record destination for the Podman service
1010
Record ssh destination for remote podman service(s). The ssh destination is given as one of:
1111
- [user@]hostname[:port]
1212
- ssh://[user@]hostname[:port]
13+
- unix://path
14+
- tcp://hostname:port
1315

1416
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.
1517

@@ -38,6 +40,10 @@ Path to the Podman service unix domain socket on the ssh destination host
3840
$ podman system connection add QA podman.example.com
3941
4042
$ podman system connection add --identity ~/.ssh/dev_rsa production ssh://[email protected]:2222
43+
44+
$ podman system connection add unix:///run/podman/podman.sock
45+
46+
$ podman system connection add tcp://localhost:8080
4147
```
4248
## SEE ALSO
4349
podman-system(1) , podman-system-connection(1) , containers.conf(5)

test/e2e/system_connection_test.go

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ var _ = Describe("podman system connection", func() {
5353
GinkgoWriter.Write([]byte(timedResult))
5454
})
5555

56-
It("add", func() {
56+
It("add ssh://", func() {
5757
cmd := []string{"system", "connection", "add",
5858
"--default",
5959
"--identity", "~/.ssh/id_rsa",
@@ -94,6 +94,68 @@ var _ = Describe("podman system connection", func() {
9494
))
9595
})
9696

97+
It("add UDS", func() {
98+
cmd := []string{"system", "connection", "add",
99+
"QA-UDS",
100+
"unix:///run/podman/podman.sock",
101+
}
102+
session := podmanTest.Podman(cmd)
103+
session.WaitWithDefaultTimeout()
104+
Expect(session).Should(Exit(0))
105+
Expect(session.Out).Should(Say(""))
106+
107+
cfg, err := config.ReadCustomConfig()
108+
Expect(err).ShouldNot(HaveOccurred())
109+
Expect(cfg.Engine.ActiveService).To(Equal("QA-UDS"))
110+
Expect(cfg.Engine.ServiceDestinations["QA-UDS"]).To(Equal(
111+
config.Destination{
112+
URI: "unix:///run/podman/podman.sock",
113+
Identity: "",
114+
},
115+
))
116+
117+
cmd = []string{"system", "connection", "add",
118+
"QA-UDS1",
119+
"--socket-path", "/run/user/podman/podman.sock",
120+
"unix:///run/podman/podman.sock",
121+
}
122+
session = podmanTest.Podman(cmd)
123+
session.WaitWithDefaultTimeout()
124+
Expect(session).Should(Exit(0))
125+
Expect(session.Out).Should(Say(""))
126+
127+
cfg, err = config.ReadCustomConfig()
128+
Expect(err).ShouldNot(HaveOccurred())
129+
Expect(cfg.Engine.ActiveService).To(Equal("QA-UDS"))
130+
Expect(cfg.Engine.ServiceDestinations["QA-UDS1"]).To(Equal(
131+
config.Destination{
132+
URI: "unix:///run/user/podman/podman.sock",
133+
Identity: "",
134+
},
135+
))
136+
})
137+
138+
It("add tcp", func() {
139+
cmd := []string{"system", "connection", "add",
140+
"QA-TCP",
141+
"tcp://localhost:8080",
142+
}
143+
session := podmanTest.Podman(cmd)
144+
session.WaitWithDefaultTimeout()
145+
Expect(session).Should(Exit(0))
146+
Expect(session.Out).Should(Say(""))
147+
148+
cfg, err := config.ReadCustomConfig()
149+
Expect(err).ShouldNot(HaveOccurred())
150+
Expect(cfg.Engine.ActiveService).To(Equal("QA-TCP"))
151+
Expect(cfg.Engine.ServiceDestinations["QA-TCP"]).To(Equal(
152+
config.Destination{
153+
URI: "tcp://localhost:8080",
154+
Identity: "",
155+
},
156+
))
157+
})
158+
97159
It("remove", func() {
98160
cmd := []string{"system", "connection", "add",
99161
"--default",

0 commit comments

Comments
 (0)