Permalink
Browse files

juju ssh, scp, and debug-hooks using SSHClient API v2

  • Loading branch information...
1 parent 928a4b4 commit d25d100f3c04eb6dc22c58db51e87c1d947a6836 Dimiter Naydenov committed Oct 20, 2016
@@ -15,11 +15,14 @@ import (
"github.com/juju/juju/api/application"
"github.com/juju/juju/cmd/modelcmd"
+ "github.com/juju/juju/network"
unitdebug "github.com/juju/juju/worker/uniter/runner/debug"
)
-func newDebugHooksCommand() cmd.Command {
- return modelcmd.Wrap(&debugHooksCommand{})
+func newDebugHooksCommand(hostDialer network.Dialer) cmd.Command {
+ c := new(debugHooksCommand)
+ c.setHostDialer(hostDialer)
+ return modelcmd.Wrap(c)
}
// debugHooksCommand is responsible for launching a ssh shell on a given unit or machine.
@@ -19,30 +19,68 @@ type DebugHooksSuite struct {
}
var debugHooksTests = []struct {
- info string
- args []string
- error string
- proxy bool
- expected *argsSpec
+ info string
+ args []string
+ dialWith dialerFunc
+ forceAPIv1 bool
+ error string
+ expected *argsSpec
}{{
- info: "unit name without hook",
- args: []string{"mysql/0"},
- proxy: true,
+ info: "literal script (api v1: unit name w/o hook or proxy)",
+ args: []string{"mysql/0"},
+ dialWith: dialerFuncFor("0.private", "0.public"),
+ forceAPIv1: true,
expected: &argsSpec{
hostKeyChecking: "yes",
knownHosts: "0",
enablePty: true,
args: "ubuntu@0.public sudo /bin/bash -c 'F=$(mktemp); echo IyEvYmluL2Jhc2gKKApjbGVhbnVwX29uX2V4aXQoKSAKeyAKCWVjaG8gIkNsZWFuaW5nIHVwIHRoZSBkZWJ1ZyBzZXNzaW9uIgoJdG11eCBraWxsLXNlc3Npb24gLXQgbXlzcWwvMDsgCn0KdHJhcCBjbGVhbnVwX29uX2V4aXQgRVhJVAoKIyBMb2NrIHRoZSBqdWp1LTx1bml0Pi1kZWJ1ZyBsb2NrZmlsZS4KZmxvY2sgLW4gOCB8fCAoCgllY2hvICJGb3VuZCBleGlzdGluZyBkZWJ1ZyBzZXNzaW9ucywgYXR0ZW1wdGluZyB0byByZWNvbm5lY3QiIDI+JjEKCWV4ZWMgdG11eCBhdHRhY2gtc2Vzc2lvbiAtdCBteXNxbC8wCglleGl0ICQ/CgkpCigKIyBDbG9zZSB0aGUgaW5oZXJpdGVkIGxvY2sgRkQsIG9yIHRtdXggd2lsbCBrZWVwIGl0IG9wZW4uCmV4ZWMgOD4mLQoKIyBXcml0ZSBvdXQgdGhlIGRlYnVnLWhvb2tzIGFyZ3MuCmVjaG8gImUzMEsiIHwgYmFzZTY0IC1kID4gL3RtcC9qdWp1LXVuaXQtbXlzcWwtMC1kZWJ1Zy1ob29rcwoKIyBMb2NrIHRoZSBqdWp1LTx1bml0Pi1kZWJ1Zy1leGl0IGxvY2tmaWxlLgpmbG9jayAtbiA5IHx8IGV4aXQgMQoKIyBXYWl0IGZvciB0bXV4IHRvIGJlIGluc3RhbGxlZC4Kd2hpbGUgWyAhIC1mIC91c3IvYmluL3RtdXggXTsgZG8KICAgIHNsZWVwIDEKZG9uZQoKaWYgWyAhIC1mIH4vLnRtdXguY29uZiBdOyB0aGVuCiAgICAgICAgaWYgWyAtZiAvdXNyL3NoYXJlL2J5b2J1L3Byb2ZpbGVzL3RtdXggXTsgdGhlbgogICAgICAgICAgICAgICAgIyBVc2UgYnlvYnUvdG11eCBwcm9maWxlIGZvciBmYW1pbGlhciBrZXliaW5kaW5ncyBhbmQgYnJhbmRpbmcKICAgICAgICAgICAgICAgIGVjaG8gInNvdXJjZS1maWxlIC91c3Ivc2hhcmUvYnlvYnUvcHJvZmlsZXMvdG11eCIgPiB+Ly50bXV4LmNvbmYKICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAjIE90aGVyd2lzZSwgdXNlIHRoZSBsZWdhY3kganVqdS90bXV4IGNvbmZpZ3VyYXRpb24KICAgICAgICAgICAgICAgIGNhdCA+IH4vLnRtdXguY29uZiA8PEVORAogICAgICAgICAgICAgICAgCiMgU3RhdHVzIGJhcgpzZXQtb3B0aW9uIC1nIHN0YXR1cy1iZyBibGFjawpzZXQtb3B0aW9uIC1nIHN0YXR1cy1mZyB3aGl0ZQoKc2V0LXdpbmRvdy1vcHRpb24gLWcgd2luZG93LXN0YXR1cy1jdXJyZW50LWJnIHJlZApzZXQtd2luZG93LW9wdGlvbiAtZyB3aW5kb3ctc3RhdHVzLWN1cnJlbnQtYXR0ciBicmlnaHQKCnNldC1vcHRpb24gLWcgc3RhdHVzLXJpZ2h0ICcnCgojIFBhbmVzCnNldC1vcHRpb24gLWcgcGFuZS1ib3JkZXItZmcgd2hpdGUKc2V0LW9wdGlvbiAtZyBwYW5lLWFjdGl2ZS1ib3JkZXItZmcgd2hpdGUKCiMgTW9uaXRvciBhY3Rpdml0eSBvbiB3aW5kb3dzCnNldC13aW5kb3ctb3B0aW9uIC1nIG1vbml0b3ItYWN0aXZpdHkgb24KCiMgU2NyZWVuIGJpbmRpbmdzLCBzaW5jZSBwZW9wbGUgYXJlIG1vcmUgZmFtaWxpYXIgd2l0aCB0aGF0LgpzZXQtb3B0aW9uIC1nIHByZWZpeCBDLWEKYmluZCBDLWEgbGFzdC13aW5kb3cKYmluZCBhIHNlbmQta2V5IEMtYQoKYmluZCB8IHNwbGl0LXdpbmRvdyAtaApiaW5kIC0gc3BsaXQtd2luZG93IC12CgojIEZpeCBDVFJMLVBHVVAvUEdET1dOIGZvciB2aW0Kc2V0LXdpbmRvdy1vcHRpb24gLWcgeHRlcm0ta2V5cyBvbgoKIyBQcmV2ZW50IEVTQyBrZXkgZnJvbSBhZGRpbmcgZGVsYXkgYW5kIGJyZWFraW5nIFZpbSdzIEVTQyA+IGFycm93IGtleQpzZXQtb3B0aW9uIC1zIGVzY2FwZS10aW1lIDAKCkVORAogICAgICAgIGZpCmZpCgooCiAgICAjIENsb3NlIHRoZSBpbmhlcml0ZWQgbG9jayBGRCwgb3IgdG11eCB3aWxsIGtlZXAgaXQgb3Blbi4KICAgIGV4ZWMgOT4mLQogICAgaWYgISB0bXV4IGhhcy1zZXNzaW9uIC10IG15c3FsLzA7IHRoZW4KCQl0bXV4IG5ldy1zZXNzaW9uIC1kIC1zIG15c3FsLzAKCWZpCgljbGllbnRfY291bnQ9JCh0bXV4IGxpc3QtY2xpZW50cyB8IHdjIC1sKQoJaWYgWyAkY2xpZW50X2NvdW50IC1nZSAxIF07IHRoZW4KCQlzZXNzaW9uX25hbWU9bXlzcWwvMCItIiRjbGllbnRfY250CgkJZXhlYyB0bXV4IG5ldy1zZXNzaW9uIC1kIC10IG15c3FsLzAgLXMgJHNlc3Npb25fbmFtZQoJCWV4ZWMgdG11eCBhdHRhY2gtc2Vzc2lvbiAtdCAkc2Vzc2lvbl9uYW1lIFw7IHNldC1vcHRpb24gZGVzdHJveS11bmF0dGFjaGVkCgllbHNlCgkgICAgZXhlYyB0bXV4IGF0dGFjaC1zZXNzaW9uIC10IG15c3FsLzAKCWZpCikKKSA5Pi90bXAvanVqdS11bml0LW15c3FsLTAtZGVidWctaG9va3MtZXhpdAopIDg+L3RtcC9qdWp1LXVuaXQtbXlzcWwtMC1kZWJ1Zy1ob29rcwpleGl0ICQ/Cg== | base64 -d > $F; . $F'",
},
}, {
- info: "proxy",
- args: []string{"--proxy=true", "mysql/0"},
+ info: "unit name without hook (api v1)",
+ args: []string{"mysql/0"},
+ dialWith: dialerFuncFor("0.private", "0.public"),
+ forceAPIv1: true,
+ expected: &argsSpec{
+ hostKeyChecking: "yes",
+ knownHosts: "0",
+ enablePty: true,
+ argsMatch: `ubuntu@0\.public sudo /bin/bash .+`,
+ },
+}, {
+ info: "unit name without hook (api v2)",
+ args: []string{"mysql/0"},
+ dialWith: dialerFuncFor("0.private", "0.public", "0.1.2.3"), // last one set on machine 0 eth0
+ forceAPIv1: false,
+ expected: &argsSpec{
+ hostKeyChecking: "yes",
+ knownHosts: "0",
+ enablePty: true,
+ argsMatch: `ubuntu@0\.(private|public|1\.2\.3) sudo .+`, // can be any of the 3
+ },
+}, {
+ info: "proxy (api v1)",
+ args: []string{"--proxy=true", "mysql/0"},
+ dialWith: dialerFuncFor("0.private", "0.public"),
+ forceAPIv1: true,
+ expected: &argsSpec{
+ hostKeyChecking: "yes",
+ knownHosts: "0",
+ enablePty: true,
+ withProxy: true,
+ argsMatch: `ubuntu@0\.private sudo /bin/bash .+`,
+ },
+}, {
+ info: "proxy (api v2)",
+ args: []string{"--proxy=true", "mysql/0"},
+ dialWith: dialerFuncFor("0.private", "0.public", "0.1.2.3"), // last one set on machine 0 eth0
+ forceAPIv1: false,
expected: &argsSpec{
hostKeyChecking: "yes",
knownHosts: "0",
enablePty: true,
withProxy: true,
- args: "ubuntu@0.private sudo /bin/bash -c 'F=$(mktemp); echo IyEvYmluL2Jhc2gKKApjbGVhbnVwX29uX2V4aXQoKSAKeyAKCWVjaG8gIkNsZWFuaW5nIHVwIHRoZSBkZWJ1ZyBzZXNzaW9uIgoJdG11eCBraWxsLXNlc3Npb24gLXQgbXlzcWwvMDsgCn0KdHJhcCBjbGVhbnVwX29uX2V4aXQgRVhJVAoKIyBMb2NrIHRoZSBqdWp1LTx1bml0Pi1kZWJ1ZyBsb2NrZmlsZS4KZmxvY2sgLW4gOCB8fCAoCgllY2hvICJGb3VuZCBleGlzdGluZyBkZWJ1ZyBzZXNzaW9ucywgYXR0ZW1wdGluZyB0byByZWNvbm5lY3QiIDI+JjEKCWV4ZWMgdG11eCBhdHRhY2gtc2Vzc2lvbiAtdCBteXNxbC8wCglleGl0ICQ/CgkpCigKIyBDbG9zZSB0aGUgaW5oZXJpdGVkIGxvY2sgRkQsIG9yIHRtdXggd2lsbCBrZWVwIGl0IG9wZW4uCmV4ZWMgOD4mLQoKIyBXcml0ZSBvdXQgdGhlIGRlYnVnLWhvb2tzIGFyZ3MuCmVjaG8gImUzMEsiIHwgYmFzZTY0IC1kID4gL3RtcC9qdWp1LXVuaXQtbXlzcWwtMC1kZWJ1Zy1ob29rcwoKIyBMb2NrIHRoZSBqdWp1LTx1bml0Pi1kZWJ1Zy1leGl0IGxvY2tmaWxlLgpmbG9jayAtbiA5IHx8IGV4aXQgMQoKIyBXYWl0IGZvciB0bXV4IHRvIGJlIGluc3RhbGxlZC4Kd2hpbGUgWyAhIC1mIC91c3IvYmluL3RtdXggXTsgZG8KICAgIHNsZWVwIDEKZG9uZQoKaWYgWyAhIC1mIH4vLnRtdXguY29uZiBdOyB0aGVuCiAgICAgICAgaWYgWyAtZiAvdXNyL3NoYXJlL2J5b2J1L3Byb2ZpbGVzL3RtdXggXTsgdGhlbgogICAgICAgICAgICAgICAgIyBVc2UgYnlvYnUvdG11eCBwcm9maWxlIGZvciBmYW1pbGlhciBrZXliaW5kaW5ncyBhbmQgYnJhbmRpbmcKICAgICAgICAgICAgICAgIGVjaG8gInNvdXJjZS1maWxlIC91c3Ivc2hhcmUvYnlvYnUvcHJvZmlsZXMvdG11eCIgPiB+Ly50bXV4LmNvbmYKICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAjIE90aGVyd2lzZSwgdXNlIHRoZSBsZWdhY3kganVqdS90bXV4IGNvbmZpZ3VyYXRpb24KICAgICAgICAgICAgICAgIGNhdCA+IH4vLnRtdXguY29uZiA8PEVORAogICAgICAgICAgICAgICAgCiMgU3RhdHVzIGJhcgpzZXQtb3B0aW9uIC1nIHN0YXR1cy1iZyBibGFjawpzZXQtb3B0aW9uIC1nIHN0YXR1cy1mZyB3aGl0ZQoKc2V0LXdpbmRvdy1vcHRpb24gLWcgd2luZG93LXN0YXR1cy1jdXJyZW50LWJnIHJlZApzZXQtd2luZG93LW9wdGlvbiAtZyB3aW5kb3ctc3RhdHVzLWN1cnJlbnQtYXR0ciBicmlnaHQKCnNldC1vcHRpb24gLWcgc3RhdHVzLXJpZ2h0ICcnCgojIFBhbmVzCnNldC1vcHRpb24gLWcgcGFuZS1ib3JkZXItZmcgd2hpdGUKc2V0LW9wdGlvbiAtZyBwYW5lLWFjdGl2ZS1ib3JkZXItZmcgd2hpdGUKCiMgTW9uaXRvciBhY3Rpdml0eSBvbiB3aW5kb3dzCnNldC13aW5kb3ctb3B0aW9uIC1nIG1vbml0b3ItYWN0aXZpdHkgb24KCiMgU2NyZWVuIGJpbmRpbmdzLCBzaW5jZSBwZW9wbGUgYXJlIG1vcmUgZmFtaWxpYXIgd2l0aCB0aGF0LgpzZXQtb3B0aW9uIC1nIHByZWZpeCBDLWEKYmluZCBDLWEgbGFzdC13aW5kb3cKYmluZCBhIHNlbmQta2V5IEMtYQoKYmluZCB8IHNwbGl0LXdpbmRvdyAtaApiaW5kIC0gc3BsaXQtd2luZG93IC12CgojIEZpeCBDVFJMLVBHVVAvUEdET1dOIGZvciB2aW0Kc2V0LXdpbmRvdy1vcHRpb24gLWcgeHRlcm0ta2V5cyBvbgoKIyBQcmV2ZW50IEVTQyBrZXkgZnJvbSBhZGRpbmcgZGVsYXkgYW5kIGJyZWFraW5nIFZpbSdzIEVTQyA+IGFycm93IGtleQpzZXQtb3B0aW9uIC1zIGVzY2FwZS10aW1lIDAKCkVORAogICAgICAgIGZpCmZpCgooCiAgICAjIENsb3NlIHRoZSBpbmhlcml0ZWQgbG9jayBGRCwgb3IgdG11eCB3aWxsIGtlZXAgaXQgb3Blbi4KICAgIGV4ZWMgOT4mLQogICAgaWYgISB0bXV4IGhhcy1zZXNzaW9uIC10IG15c3FsLzA7IHRoZW4KCQl0bXV4IG5ldy1zZXNzaW9uIC1kIC1zIG15c3FsLzAKCWZpCgljbGllbnRfY291bnQ9JCh0bXV4IGxpc3QtY2xpZW50cyB8IHdjIC1sKQoJaWYgWyAkY2xpZW50X2NvdW50IC1nZSAxIF07IHRoZW4KCQlzZXNzaW9uX25hbWU9bXlzcWwvMCItIiRjbGllbnRfY250CgkJZXhlYyB0bXV4IG5ldy1zZXNzaW9uIC1kIC10IG15c3FsLzAgLXMgJHNlc3Npb25fbmFtZQoJCWV4ZWMgdG11eCBhdHRhY2gtc2Vzc2lvbiAtdCAkc2Vzc2lvbl9uYW1lIFw7IHNldC1vcHRpb24gZGVzdHJveS11bmF0dGFjaGVkCgllbHNlCgkgICAgZXhlYyB0bXV4IGF0dGFjaC1zZXNzaW9uIC10IG15c3FsLzAKCWZpCikKKSA5Pi90bXAvanVqdS11bml0LW15c3FsLTAtZGVidWctaG9va3MtZXhpdAopIDg+L3RtcC9qdWp1LXVuaXQtbXlzcWwtMC1kZWJ1Zy1ob29rcwpleGl0ICQ/Cg== | base64 -d > $F; . $F'",
+ argsMatch: `ubuntu@0\.(private|public|1\.2\.3) sudo .+`, // can be any of the 3
},
}, {
info: `"*" is a valid hook name: it means hook everything`,
@@ -72,6 +110,10 @@ var debugHooksTests = []struct {
info: `invalid hook`,
args: []string{"mysql/0", "invalid-hook"},
error: `unit "mysql/0" does not contain hook "invalid-hook"`,
+}, {
+ info: `no args at all`,
+ args: nil,
+ error: `no unit name specified`,
}}
func (s *DebugHooksSuite) TestDebugHooksCommand(c *gc.C) {
@@ -85,7 +127,10 @@ func (s *DebugHooksSuite) TestDebugHooksCommand(c *gc.C) {
for i, t := range debugHooksTests {
c.Logf("test %d: %s\n\t%s\n", i, t.info, t.args)
- ctx, err := coretesting.RunCommand(c, newDebugHooksCommand(), t.args...)
+ s.setHostDialerFunc(t.dialWith)
+ s.setForceAPIv1(t.forceAPIv1)
+
+ ctx, err := coretesting.RunCommand(c, newDebugHooksCommand(s.hostDialer), t.args...)
if t.error != "" {
c.Check(err, gc.ErrorMatches, t.error)
} else {
@@ -246,11 +246,11 @@ func registerCommands(r commandRegistry, ctx *cmd.Context) {
// Error resolution and debugging commands.
r.Register(newRunCommand())
- r.Register(newSCPCommand())
- r.Register(newSSHCommand())
+ r.Register(newSCPCommand(nil))
+ r.Register(newSSHCommand(nil))
r.Register(newResolvedCommand())
r.Register(newDebugLogCommand())
- r.Register(newDebugHooksCommand())
+ r.Register(newDebugHooksCommand(nil))
// Configuration commands.
r.Register(model.NewModelGetConstraintsCommand())
View
@@ -12,6 +12,7 @@ import (
"github.com/juju/utils/ssh"
"github.com/juju/juju/cmd/modelcmd"
+ "github.com/juju/juju/network"
)
var usageSCPSummary = `
@@ -72,8 +73,10 @@ causes the transfer to be made via the client):
See also:
ssh`
-func newSCPCommand() cmd.Command {
- return modelcmd.Wrap(&scpCommand{})
+func newSCPCommand(hostDialer network.Dialer) cmd.Command {
+ c := new(scpCommand)
+ c.setHostDialer(hostDialer)
+ return modelcmd.Wrap(c)
}
// scpCommand is responsible for launching a scp command to copy files to/from remote machine(s)
@@ -22,30 +22,46 @@ type SCPSuite struct {
}
var scpTests = []struct {
- about string
- args []string
- expected argsSpec
- error string
+ about string
+ args []string
+ dialWith dialerFunc
+ forceAPIv1 bool
+ expected argsSpec
+ error string
}{
{
- about: "scp from machine 0 to current dir",
- args: []string{"0:foo", "."},
+ about: "scp from machine 0 to current dir (api v1)",
+ args: []string{"0:foo", "."},
+ dialWith: dialerFuncFor("0.private", "0.public"),
+ forceAPIv1: true,
expected: argsSpec{
args: "ubuntu@0.public:foo .",
hostKeyChecking: "yes",
knownHosts: "0",
},
}, {
- about: "scp from machine 0 to current dir with extra args",
- args: []string{"0:foo", ".", "-rv", "-o", "SomeOption"},
+ about: "scp from machine 0 to current dir (api v2)",
+ args: []string{"0:foo", "."},
+ dialWith: dialerFuncFor("0.private", "0.public", "0.1.2.3"), // last one set on machine 0 eth0
+ forceAPIv1: false,
+ expected: argsSpec{
+ argsMatch: `ubuntu@0.(public|private|1\.2\.3):foo \.`, // can be any of the 3
+ hostKeyChecking: "yes",
+ knownHosts: "0",
+ },
+ }, {
+ about: "scp from machine 0 to current dir with extra args",
+ args: []string{"0:foo", ".", "-rv", "-o", "SomeOption"},
+ dialWith: dialerFuncFor("0.private", "0.public"),
expected: argsSpec{
args: "ubuntu@0.public:foo . -rv -o SomeOption",
hostKeyChecking: "yes",
knownHosts: "0",
},
}, {
- about: "scp from current dir to machine 0",
- args: []string{"foo", "0:"},
+ about: "scp from current dir to machine 0",
+ args: []string{"foo", "0:"},
+ dialWith: dialerFuncFor("0.private", "0.public"),
expected: argsSpec{
args: "foo ubuntu@0.public:",
hostKeyChecking: "yes",
@@ -56,32 +72,36 @@ var scpTests = []struct {
args: []string{"foo", "1:"},
error: `retrieving SSH host keys for "1": keys not found`,
}, {
- about: "scp when no keys available, with --no-host-key-checks",
- args: []string{"--no-host-key-checks", "foo", "1:"},
+ about: "scp when no keys available, with --no-host-key-checks",
+ args: []string{"--no-host-key-checks", "foo", "1:"},
+ dialWith: dialerFuncFor("1.private", "1.public"),
expected: argsSpec{
args: "foo ubuntu@1.public:",
hostKeyChecking: "no",
knownHosts: "null",
},
}, {
- about: "scp from current dir to machine 0 with extra args",
- args: []string{"foo", "0:", "-r", "-v"},
+ about: "scp from current dir to machine 0 with extra args",
+ args: []string{"foo", "0:", "-r", "-v"},
+ dialWith: dialerFuncFor("0.private", "0.public"),
expected: argsSpec{
args: "foo ubuntu@0.public: -r -v",
hostKeyChecking: "yes",
knownHosts: "0",
},
}, {
- about: "scp from machine 0 to unit mysql/0",
- args: []string{"0:foo", "mysql/0:/foo"},
+ about: "scp from machine 0 to unit mysql/0",
+ args: []string{"0:foo", "mysql/0:/foo"},
+ dialWith: dialerFuncFor("0.private", "0.public"),
expected: argsSpec{
args: "ubuntu@0.public:foo ubuntu@0.public:/foo",
hostKeyChecking: "yes",
knownHosts: "0",
},
}, {
- about: "scp from machine 0 to unit mysql/0 and extra args",
- args: []string{"0:foo", "mysql/0:/foo", "-q"},
+ about: "scp from machine 0 to unit mysql/0 and extra args",
+ args: []string{"0:foo", "mysql/0:/foo", "-q"},
+ dialWith: dialerFuncFor("0.private", "0.public"),
expected: argsSpec{
args: "ubuntu@0.public:foo ubuntu@0.public:/foo -q",
hostKeyChecking: "yes",
@@ -92,49 +112,55 @@ var scpTests = []struct {
args: []string{"-q", "-r", "0:foo", "mysql/0:/foo"},
error: "flag provided but not defined: -q",
}, {
- about: "scp two local files to unit mysql/0",
- args: []string{"file1", "file2", "mysql/0:/foo/"},
+ about: "scp two local files to unit mysql/0",
+ args: []string{"file1", "file2", "mysql/0:/foo/"},
+ dialWith: dialerFuncFor("0.private", "0.public"),
expected: argsSpec{
args: "file1 file2 ubuntu@0.public:/foo/",
hostKeyChecking: "yes",
knownHosts: "0",
},
}, {
- about: "scp from machine 0 to unit mysql/0 and multiple extra args",
- args: []string{"0:foo", "mysql/0:", "-r", "-v", "-q", "-l5"},
+ about: "scp from machine 0 to unit mysql/0 and multiple extra args",
+ args: []string{"0:foo", "mysql/0:", "-r", "-v", "-q", "-l5"},
+ dialWith: dialerFuncFor("0.private", "0.public"),
expected: argsSpec{
args: "ubuntu@0.public:foo ubuntu@0.public: -r -v -q -l5",
hostKeyChecking: "yes",
knownHosts: "0",
},
}, {
- about: "scp works with IPv6 addresses",
- args: []string{"2:foo", "bar"},
+ about: "scp works with IPv6 addresses",
+ args: []string{"2:foo", "bar"},
+ dialWith: dialerFuncFor("2001:db8::1"),
expected: argsSpec{
args: `ubuntu@[2001:db8::1]:foo bar`,
hostKeyChecking: "yes",
knownHosts: "2",
},
}, {
- about: "scp from machine 0 to unit mysql/0 with proxy",
- args: []string{"--proxy=true", "0:foo", "mysql/0:/bar"},
+ about: "scp from machine 0 to unit mysql/0 with proxy",
+ args: []string{"--proxy=true", "0:foo", "mysql/0:/bar"},
+ dialWith: dialerFuncFor("0.private"),
expected: argsSpec{
args: "ubuntu@0.private:foo ubuntu@0.private:/bar",
withProxy: true,
hostKeyChecking: "yes",
knownHosts: "0",
},
}, {
- about: "scp from unit mysql/0 to machine 2 with a --",
- args: []string{"--", "-r", "-v", "mysql/0:foo", "2:", "-q", "-l5"},
+ about: "scp from unit mysql/0 to machine 2 with a --",
+ args: []string{"--", "-r", "-v", "mysql/0:foo", "2:", "-q", "-l5"},
+ dialWith: dialerFuncFor("0.public", "0.private", "2001:db8::1"),
expected: argsSpec{
args: "-r -v ubuntu@0.public:foo ubuntu@[2001:db8::1]: -q -l5",
hostKeyChecking: "yes",
knownHosts: "0,2",
},
}, {
- about: "scp from unit mysql/0 to current dir as 'sam' user",
- args: []string{"sam@mysql/0:foo", "."},
+ about: "scp from unit mysql/0 to current dir as 'sam' user",
+ args: []string{"sam@mysql/0:foo", "."},
+ dialWith: dialerFuncFor("0.private", "0.public"),
expected: argsSpec{
args: "sam@0.public:foo .",
hostKeyChecking: "yes",
@@ -145,15 +171,17 @@ var scpTests = []struct {
args: []string{"5:foo", "bar"},
error: `machine 5 not found`,
}, {
- about: "scp from arbitrary host name to current dir",
- args: []string{"some.host:foo", "."},
+ about: "scp from arbitrary host name to current dir",
+ args: []string{"some.host:foo", "."},
+ dialWith: dialerFuncFor("some.host"),
expected: argsSpec{
args: "some.host:foo .",
hostKeyChecking: "",
},
}, {
- about: "scp from arbitrary user & host to current dir",
- args: []string{"someone@some.host:foo", "."},
+ about: "scp from arbitrary user & host to current dir",
+ args: []string{"someone@some.host:foo", "."},
+ dialWith: dialerFuncFor("some.host"),
expected: argsSpec{
args: "someone@some.host:foo .",
hostKeyChecking: "",
@@ -163,13 +191,20 @@ var scpTests = []struct {
args: []string{"some.host:foo", "0:"},
error: `can't determine host keys for all targets: consider --no-host-key-checks`,
}, {
- about: "scp with arbitrary host name and an entity, --no-host-key-checks",
- args: []string{"--no-host-key-checks", "some.host:foo", "0:"},
+ about: "scp with arbitrary host name and an entity, --no-host-key-checks, --proxy (api v1)",
+ args: []string{"--no-host-key-checks", "--proxy", "some.host:foo", "0:"},
+ dialWith: dialerFuncFor("some.host", "0.public", "0.private"),
+ forceAPIv1: true,
expected: argsSpec{
- args: "some.host:foo ubuntu@0.public:",
+ args: "some.host:foo ubuntu@0.private:",
hostKeyChecking: "no",
+ withProxy: true,
knownHosts: "null",
},
+ }, {
+ about: "scp with no arguments",
+ args: nil,
+ error: `at least two arguments required`,
},
}
@@ -179,7 +214,10 @@ func (s *SCPSuite) TestSCPCommand(c *gc.C) {
for i, t := range scpTests {
c.Logf("test %d: %s -> %s\n", i, t.about, t.args)
- ctx, err := coretesting.RunCommand(c, newSCPCommand(), t.args...)
+ s.setHostDialerFunc(t.dialWith)
+ s.setForceAPIv1(t.forceAPIv1)
+
+ ctx, err := coretesting.RunCommand(c, newSCPCommand(s.hostDialer), t.args...)
if t.error != "" {
c.Check(err, gc.ErrorMatches, t.error)
} else {
Oops, something went wrong.

0 comments on commit d25d100

Please sign in to comment.