Use address of ssh daemon when creating a tunnel 17/180917/9
authorAleksander Mistewicz <a.mistewicz@samsung.com>
Mon, 4 Jun 2018 08:10:56 +0000 (10:10 +0200)
committerAleksander Mistewicz <a.mistewicz@samsung.com>
Fri, 3 Aug 2018 11:36:41 +0000 (13:36 +0200)
Change-Id: Ie66daa17104be1ea06849eccaaee78b2b4353c2e
Signed-off-by: Aleksander Mistewicz <a.mistewicz@samsung.com>
Use net.TCPAddr instead of net.IP as it contains Port field.

Some methods were renamed to reflect migration from net.IP to
net.TCPAddr. It allows multiple dryads to coexist behind NAT or on
a single host. Currently, it is possible to provide network addresses to
non-existent address or to a different dryad than expected. Addresses in
Register() call are checked only for resolvability.

Change-Id: I46cecb8ad6f06fabb88f2262d95c0678329915ab
Signed-off-by: Aleksander Mistewicz <a.mistewicz@samsung.com>
17 files changed:
matcher/jobs.go
matcher/jobs_test.go
matcher/tunneler_mock_test.go
matcher/workersmanager.go
matcher/workersmanager_mock_test.go
requests/requests_requestsmanager_test.go
requests/workersmanager_mock_test.go
rpc/dryad/clientmanager.go
rpc/dryad/tcpdial.go
rpc/superviser/reception_test.go
tunnels/tunneler.go
tunnels/tunnels.go
tunnels/tunnels_test.go
workers/dryadclientmanager_mock_test.go
workers/error.go
workers/worker_list_test.go
workers/workers.go

index 7b0cbd5..d2f6b3c 100644 (file)
@@ -75,7 +75,7 @@ func (m *JobsManagerImpl) Create(req ReqID, worker WorkerUUID) error {
                return ErrJobAlreadyExists
        }
 
-       ip, err := m.workers.GetWorkerIP(worker)
+       addr, err := m.workers.GetWorkerSSHAddr(worker)
        if err != nil {
                return err
        }
@@ -84,7 +84,7 @@ func (m *JobsManagerImpl) Create(req ReqID, worker WorkerUUID) error {
                return err
        }
        t := m.newTunnel()
-       err = t.Create(nil, ip)
+       err = t.Create(nil, addr)
        if err != nil {
                return err
        }
index 558011d..1782d09 100644 (file)
@@ -16,6 +16,9 @@
 
 package matcher
 
+//go:generate mockgen -package matcher -destination=workersmanager_mock_test.go -write_package_comment=false git.tizen.org/tools/boruta/matcher WorkersManager
+//go:generate mockgen -package matcher -destination=tunneler_mock_test.go -write_package_comment=false git.tizen.org/tools/boruta/tunnels Tunneler
+
 import (
        "crypto/rsa"
        "errors"
@@ -55,16 +58,16 @@ var _ = Describe("Jobs", func() {
        })
        Describe("With prepared job data", func() {
                var (
-                       ctrl    *gomock.Controller
-                       w       *MockWorkersManager
-                       ttm     *MockTunneler
-                       jm      JobsManager
-                       ip      net.IP         = net.IPv4(5, 6, 7, 8)
-                       key     rsa.PrivateKey = rsa.PrivateKey{}
-                       addr    net.Addr       = &net.TCPAddr{IP: net.IPv4(10, 11, 12, 13), Port: 12345}
-                       req     ReqID          = ReqID(67)
-                       worker  WorkerUUID     = WorkerUUID("TestWorker")
-                       testerr error          = errors.New("TestError")
+                       ctrl       *gomock.Controller
+                       w          *MockWorkersManager
+                       ttm        *MockTunneler
+                       jm         JobsManager
+                       workerAddr net.TCPAddr    = net.TCPAddr{IP: net.IPv4(5, 6, 7, 8), Port: 7357}
+                       key        rsa.PrivateKey = rsa.PrivateKey{}
+                       addr       net.Addr       = &net.TCPAddr{IP: net.IPv4(10, 11, 12, 13), Port: 12345}
+                       req        ReqID          = ReqID(67)
+                       worker     WorkerUUID     = WorkerUUID("TestWorker")
+                       testerr    error          = errors.New("TestError")
                )
                BeforeEach(func() {
                        ctrl = gomock.NewController(GinkgoT())
@@ -84,9 +87,9 @@ var _ = Describe("Jobs", func() {
                Describe("Create", func() {
                        It("should create a new, properly initialized job", func() {
                                gomock.InOrder(
-                                       w.EXPECT().GetWorkerIP(worker).Return(ip, nil),
+                                       w.EXPECT().GetWorkerSSHAddr(worker).Return(workerAddr, nil),
                                        w.EXPECT().GetWorkerKey(worker).Return(key, nil),
-                                       ttm.EXPECT().Create(nil, ip).Return(nil),
+                                       ttm.EXPECT().Create(nil, workerAddr).Return(nil),
                                        ttm.EXPECT().Addr().Return(addr),
                                )
 
@@ -100,9 +103,9 @@ var _ = Describe("Jobs", func() {
                        })
                        It("should fail to create another job for same worker", func() {
                                gomock.InOrder(
-                                       w.EXPECT().GetWorkerIP(worker).Return(ip, nil),
+                                       w.EXPECT().GetWorkerSSHAddr(worker).Return(workerAddr, nil),
                                        w.EXPECT().GetWorkerKey(worker).Return(key, nil),
-                                       ttm.EXPECT().Create(nil, ip).Return(nil),
+                                       ttm.EXPECT().Create(nil, workerAddr).Return(nil),
                                        ttm.EXPECT().Addr().Return(addr),
                                )
 
@@ -114,15 +117,15 @@ var _ = Describe("Jobs", func() {
                                err = jm.Create(req, worker)
                                Expect(err).To(Equal(ErrJobAlreadyExists))
                        })
-                       It("should fail when GetWorkerIP fails", func() {
-                               w.EXPECT().GetWorkerIP(worker).Return(nil, testerr)
+                       It("should fail when GetWorkerSSHAddr fails", func() {
+                               w.EXPECT().GetWorkerSSHAddr(worker).Return(net.TCPAddr{}, testerr)
 
                                err := jm.Create(req, worker)
                                Expect(err).To(Equal(testerr))
                        })
                        It("should fail and close tunnel when GetWorkerKey fails", func() {
                                gomock.InOrder(
-                                       w.EXPECT().GetWorkerIP(worker).Return(ip, nil),
+                                       w.EXPECT().GetWorkerSSHAddr(worker).Return(workerAddr, nil),
                                        w.EXPECT().GetWorkerKey(worker).Return(rsa.PrivateKey{}, testerr),
                                )
 
@@ -131,9 +134,9 @@ var _ = Describe("Jobs", func() {
                        })
                        It("should fail when tunnel creation fails", func() {
                                gomock.InOrder(
-                                       w.EXPECT().GetWorkerIP(worker).Return(ip, nil),
+                                       w.EXPECT().GetWorkerSSHAddr(worker).Return(workerAddr, nil),
                                        w.EXPECT().GetWorkerKey(worker).Return(key, nil),
-                                       ttm.EXPECT().Create(nil, ip).Return(testerr),
+                                       ttm.EXPECT().Create(nil, workerAddr).Return(testerr),
                                )
 
                                err := jm.Create(req, worker)
@@ -143,9 +146,9 @@ var _ = Describe("Jobs", func() {
                Describe("Get", func() {
                        It("should get existing job", func() {
                                gomock.InOrder(
-                                       w.EXPECT().GetWorkerIP(worker).Return(ip, nil),
+                                       w.EXPECT().GetWorkerSSHAddr(worker).Return(workerAddr, nil),
                                        w.EXPECT().GetWorkerKey(worker).Return(key, nil),
-                                       ttm.EXPECT().Create(nil, ip).Return(nil),
+                                       ttm.EXPECT().Create(nil, workerAddr).Return(nil),
                                        ttm.EXPECT().Addr().Return(addr),
                                )
 
@@ -166,9 +169,9 @@ var _ = Describe("Jobs", func() {
                Describe("Finish", func() {
                        It("should finish existing job", func() {
                                gomock.InOrder(
-                                       w.EXPECT().GetWorkerIP(worker).Return(ip, nil),
+                                       w.EXPECT().GetWorkerSSHAddr(worker).Return(workerAddr, nil),
                                        w.EXPECT().GetWorkerKey(worker).Return(key, nil),
-                                       ttm.EXPECT().Create(nil, ip).Return(nil),
+                                       ttm.EXPECT().Create(nil, workerAddr).Return(nil),
                                        ttm.EXPECT().Addr().Return(addr),
                                        ttm.EXPECT().Close(),
                                        w.EXPECT().PrepareWorker(worker, true),
index 27def65..1a886f1 100644 (file)
@@ -57,7 +57,7 @@ func (mr *MockTunnelerMockRecorder) Close() *gomock.Call {
 }
 
 // Create mocks base method
-func (m *MockTunneler) Create(arg0, arg1 net.IP) error {
+func (m *MockTunneler) Create(arg0 net.IP, arg1 net.TCPAddr) error {
        ret := m.ctrl.Call(m, "Create", arg0, arg1)
        ret0, _ := ret[0].(error)
        return ret0
index 5214abc..64ad1ea 100644 (file)
@@ -38,10 +38,10 @@ type WorkersManager interface {
        // is required for preparing worker.
        PrepareWorker(worker WorkerUUID, withKeyGeneration bool) error
 
-       // GetWorkerIP returns IP of the worker that can be used for setting up tunnel
-       // to the worker. If there is no worker with given WorkerUUID an error
-       // is returned.
-       GetWorkerIP(WorkerUUID) (net.IP, error)
+       // GetWorkerSSHAddr returns address of the ssh daemon on the worker that can
+       // be used for setting up tunnel to the worker. If there is no worker with
+       // given WorkerUUID an error is returned.
+       GetWorkerSSHAddr(WorkerUUID) (net.TCPAddr, error)
 
        // GetWorkerKey returns private RSA key of the worker that can be used for
        // accessing the worker. If there is no worker with given WorkerUUID an error
index 17e5f54..4385730 100644 (file)
@@ -35,19 +35,6 @@ func (m *MockWorkersManager) EXPECT() *MockWorkersManagerMockRecorder {
        return m.recorder
 }
 
-// GetWorkerIP mocks base method
-func (m *MockWorkersManager) GetWorkerIP(arg0 boruta.WorkerUUID) (net.IP, error) {
-       ret := m.ctrl.Call(m, "GetWorkerIP", arg0)
-       ret0, _ := ret[0].(net.IP)
-       ret1, _ := ret[1].(error)
-       return ret0, ret1
-}
-
-// GetWorkerIP indicates an expected call of GetWorkerIP
-func (mr *MockWorkersManagerMockRecorder) GetWorkerIP(arg0 interface{}) *gomock.Call {
-       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkerIP", reflect.TypeOf((*MockWorkersManager)(nil).GetWorkerIP), arg0)
-}
-
 // GetWorkerKey mocks base method
 func (m *MockWorkersManager) GetWorkerKey(arg0 boruta.WorkerUUID) (rsa.PrivateKey, error) {
        ret := m.ctrl.Call(m, "GetWorkerKey", arg0)
@@ -61,6 +48,19 @@ func (mr *MockWorkersManagerMockRecorder) GetWorkerKey(arg0 interface{}) *gomock
        return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkerKey", reflect.TypeOf((*MockWorkersManager)(nil).GetWorkerKey), arg0)
 }
 
+// GetWorkerSSHAddr mocks base method
+func (m *MockWorkersManager) GetWorkerSSHAddr(arg0 boruta.WorkerUUID) (net.TCPAddr, error) {
+       ret := m.ctrl.Call(m, "GetWorkerSSHAddr", arg0)
+       ret0, _ := ret[0].(net.TCPAddr)
+       ret1, _ := ret[1].(error)
+       return ret0, ret1
+}
+
+// GetWorkerSSHAddr indicates an expected call of GetWorkerSSHAddr
+func (mr *MockWorkersManagerMockRecorder) GetWorkerSSHAddr(arg0 interface{}) *gomock.Call {
+       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkerSSHAddr", reflect.TypeOf((*MockWorkersManager)(nil).GetWorkerSSHAddr), arg0)
+}
+
 // PrepareWorker mocks base method
 func (m *MockWorkersManager) PrepareWorker(arg0 boruta.WorkerUUID, arg1 bool) error {
        ret := m.ctrl.Call(m, "PrepareWorker", arg0, arg1)
index 305bd5f..6743cb8 100644 (file)
@@ -16,6 +16,8 @@
 
 package requests
 
+//go:generate mockgen -package requests -destination=workersmanager_mock_test.go -write_package_comment=false git.tizen.org/tools/boruta/matcher WorkersManager
+
 import (
        "errors"
        "time"
index 2f7566d..6f8b617 100644 (file)
@@ -35,19 +35,6 @@ func (m *MockWorkersManager) EXPECT() *MockWorkersManagerMockRecorder {
        return m.recorder
 }
 
-// GetWorkerIP mocks base method
-func (m *MockWorkersManager) GetWorkerIP(arg0 boruta.WorkerUUID) (net.IP, error) {
-       ret := m.ctrl.Call(m, "GetWorkerIP", arg0)
-       ret0, _ := ret[0].(net.IP)
-       ret1, _ := ret[1].(error)
-       return ret0, ret1
-}
-
-// GetWorkerIP indicates an expected call of GetWorkerIP
-func (mr *MockWorkersManagerMockRecorder) GetWorkerIP(arg0 interface{}) *gomock.Call {
-       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkerIP", reflect.TypeOf((*MockWorkersManager)(nil).GetWorkerIP), arg0)
-}
-
 // GetWorkerKey mocks base method
 func (m *MockWorkersManager) GetWorkerKey(arg0 boruta.WorkerUUID) (rsa.PrivateKey, error) {
        ret := m.ctrl.Call(m, "GetWorkerKey", arg0)
@@ -61,6 +48,19 @@ func (mr *MockWorkersManagerMockRecorder) GetWorkerKey(arg0 interface{}) *gomock
        return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkerKey", reflect.TypeOf((*MockWorkersManager)(nil).GetWorkerKey), arg0)
 }
 
+// GetWorkerSSHAddr mocks base method
+func (m *MockWorkersManager) GetWorkerSSHAddr(arg0 boruta.WorkerUUID) (net.TCPAddr, error) {
+       ret := m.ctrl.Call(m, "GetWorkerSSHAddr", arg0)
+       ret0, _ := ret[0].(net.TCPAddr)
+       ret1, _ := ret[1].(error)
+       return ret0, ret1
+}
+
+// GetWorkerSSHAddr indicates an expected call of GetWorkerSSHAddr
+func (mr *MockWorkersManagerMockRecorder) GetWorkerSSHAddr(arg0 interface{}) *gomock.Call {
+       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkerSSHAddr", reflect.TypeOf((*MockWorkersManager)(nil).GetWorkerSSHAddr), arg0)
+}
+
 // PrepareWorker mocks base method
 func (m *MockWorkersManager) PrepareWorker(arg0 boruta.WorkerUUID, arg1 bool) error {
        ret := m.ctrl.Call(m, "PrepareWorker", arg0, arg1)
index f4f4b18..4ebe3a5 100644 (file)
@@ -31,7 +31,7 @@ import (
 type ClientManager interface {
        Dryad
        // Create creates a new RPC client.
-       Create(net.IP, int) error
+       Create(*net.TCPAddr) error
        // Close shuts down RPC client connection.
        Close() error
 }
index 8d5bfa1..717a503 100644 (file)
@@ -26,8 +26,7 @@ import (
 
 // Create sets up new TCP dialled RPC client in DryadClient structure.
 // The Create function implements ClientManager interface.
-func (_c *DryadClient) Create(ip net.IP, port int) error {
-       addr := &net.TCPAddr{IP: ip, Port: port}
+func (_c *DryadClient) Create(addr *net.TCPAddr) error {
        conn, err := net.DialTCP("tcp", nil, addr)
        if err != nil {
                return err
index 890c51b..ac38912 100644 (file)
@@ -54,23 +54,22 @@ var _ = Describe("superviserReception", func() {
                err = c.Register(boruta.Capabilities{"UUID": uuidStr}, ":7175", ":22")
                Expect(err).ToNot(HaveOccurred())
 
-               ip, err := wl.GetWorkerIP(uuid)
+               addr, err := wl.GetWorkerAddr(uuid)
                Expect(err).ToNot(HaveOccurred())
-               Expect(ip).ToNot(BeNil())
+               Expect(addr).To(Equal(refAddr))
        })
 
        It("should get IP from argument", func() {
-               refIP := net.IPv4(127, 0, 0, 1)
                uuid := boruta.WorkerUUID(uuidStr)
                c, err := DialSuperviserClient(addr.String())
                Expect(err).ToNot(HaveOccurred())
 
-               err = c.Register(boruta.Capabilities{"UUID": uuidStr}, refIP.String()+":7175", refIP.String()+":22")
+               err = c.Register(boruta.Capabilities{"UUID": uuidStr}, refAddr.String(), refAddr.IP.String()+":22")
                Expect(err).ToNot(HaveOccurred())
 
-               ip, err := wl.GetWorkerIP(uuid)
+               addr, err := wl.GetWorkerAddr(uuid)
                Expect(err).ToNot(HaveOccurred())
-               Expect(ip).To(Equal(refIP))
+               Expect(addr).To(Equal(refAddr))
        })
 
        It("should fail to call with either address empty", func() {
index 8f369b1..587a5cf 100644 (file)
@@ -26,7 +26,7 @@ import (
 // Tunneler defines API for basic operations on tunnels.
 type Tunneler interface {
        // Create sets up a new tunnel.
-       Create(net.IP, net.IP) error
+       Create(net.IP, net.TCPAddr) error
        // Close shuts down tunnel.
        Close() error
        // Addr returns the address of the tunnel to be used by a user
index d8409db..6df33d9 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 // Package tunnels allows creation of simple forwarding tunnels
-// between IP addresses pairs.
+// between address pairs.
 package tunnels
 
 import (
@@ -23,9 +23,6 @@ import (
        "net"
 )
 
-// defaultSSHPort is a default port used for connection to dest by Tunnel.
-const defaultSSHPort = 22
-
 // Tunnel forwards data between source and destination addresses.
 type Tunnel struct {
        Tunneler
@@ -34,21 +31,15 @@ type Tunnel struct {
        done     chan struct{}
 }
 
-// Create sets up data forwarding tunnel between src and dest IP addresses.
-// It will listen on random port on src and forward to SSH port (22) of dest.
+// Create sets up data forwarding tunnel between src and dest addresses.
+// It will listen on random port on src and forward to dest.
 //
 // When connection to src is made a corresponding one is created to dest
 // and data is copied between them.
 //
 // Close should be called to clean up this function and terminate connections.
-func (t *Tunnel) Create(src, dest net.IP) (err error) {
-       return t.create(src, dest, defaultSSHPort)
-}
-
-// create is a helper function for Create method, which allows to setup any
-// port for testing purposes.
-func (t *Tunnel) create(src, dest net.IP, portSSH int) (err error) {
-       t.dest = &net.TCPAddr{IP: dest, Port: portSSH}
+func (t *Tunnel) Create(src net.IP, dest net.TCPAddr) (err error) {
+       t.dest = &dest
        t.done = make(chan struct{})
        // It will listen on a random port.
        t.listener, err = net.ListenTCP("tcp", &net.TCPAddr{IP: src})
index 8ecbcd5..57f7358 100644 (file)
@@ -71,7 +71,7 @@ var _ = Describe("Tunnels", func() {
        It("should make a connection", func() {
                done := make(chan struct{})
                lAddr := listen(done, "", "")
-               err := t.create(localIP, localIP, lAddr.Port)
+               err := t.Create(localIP, lAddr)
                Expect(err).ToNot(HaveOccurred())
 
                lAddr.IP = localIP
@@ -88,7 +88,7 @@ var _ = Describe("Tunnels", func() {
                testIn := "input test string"
                testOut := "output test string"
                lAddr := listen(done, testIn, testOut)
-               err := t.create(localIP, localIP, lAddr.Port)
+               err := t.Create(localIP, lAddr)
                Expect(err).ToNot(HaveOccurred())
                conn, err := net.DialTCP("tcp", nil, t.Addr().(*net.TCPAddr))
                Expect(err).ToNot(HaveOccurred())
@@ -106,12 +106,12 @@ var _ = Describe("Tunnels", func() {
        })
 
        It("should fail to listen on invalid address", func() {
-               err := t.Create(invalidIP, nil)
+               err := t.Create(invalidIP, net.TCPAddr{})
                Expect(err).To(HaveOccurred())
        })
 
        It("should fail to connect to invalid address", func() {
-               err := t.create(localIP, localIP, 0)
+               err := t.Create(localIP, net.TCPAddr{})
                Expect(err).ToNot(HaveOccurred())
 
                conn, err := net.DialTCP("tcp", nil, t.Addr().(*net.TCPAddr))
index 1d46791..8db3a0d 100644 (file)
@@ -46,15 +46,15 @@ func (mr *MockDryadClientManagerMockRecorder) Close() *gomock.Call {
 }
 
 // Create mocks base method
-func (m *MockDryadClientManager) Create(arg0 net.IP, arg1 int) error {
-       ret := m.ctrl.Call(m, "Create", arg0, arg1)
+func (m *MockDryadClientManager) Create(arg0 *net.TCPAddr) error {
+       ret := m.ctrl.Call(m, "Create", arg0)
        ret0, _ := ret[0].(error)
        return ret0
 }
 
 // Create indicates an expected call of Create
-func (mr *MockDryadClientManagerMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call {
-       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockDryadClientManager)(nil).Create), arg0, arg1)
+func (mr *MockDryadClientManagerMockRecorder) Create(arg0 interface{}) *gomock.Call {
+       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockDryadClientManager)(nil).Create), arg0)
 }
 
 // Healthcheck mocks base method
index 6cf60bd..455ab1c 100644 (file)
@@ -44,4 +44,10 @@ var (
        // ErrNoMatchingWorker is returned when there is no worker matching groups nor
        // capabilities required by request.
        ErrNoMatchingWorker = errors.New("No matching worker")
+       // ErrMissingIP is returned when Register is called with either dryad or sshd
+       // address missing IP value.
+       ErrMissingIP = errors.New("IP address is missing from address")
+       // ErrMissingPort is returned when Register is called with either dryad or sshd
+       // address missing Port value.
+       ErrMissingPort = errors.New("Port is missing from address")
 )
index 1c85098..6c17bc2 100644 (file)
@@ -24,26 +24,29 @@ import (
        "net"
 
        . "git.tizen.org/tools/boruta"
-       "git.tizen.org/tools/boruta/dryad/conf"
        "git.tizen.org/tools/boruta/rpc/dryad"
 
        gomock "github.com/golang/mock/gomock"
        . "github.com/onsi/ginkgo"
        . "github.com/onsi/ginkgo/extensions/table"
        . "github.com/onsi/gomega"
+       "github.com/onsi/gomega/types"
        "github.com/satori/go.uuid"
 )
 
 var _ = Describe("WorkerList", func() {
        var wl *WorkerList
-       dryadAddr := net.TCPAddr{
+       dryadAddr := &net.TCPAddr{
                IP:   net.IPv4(127, 0, 0, 1),
                Port: 7175,
        }
-       sshdAddr := net.TCPAddr{
+       sshdAddr := &net.TCPAddr{
                IP:   net.IPv4(127, 0, 0, 1),
                Port: 22,
        }
+       missingPort := &net.TCPAddr{
+               IP: dryadAddr.IP,
+       }
        BeforeEach(func() {
                wl = NewWorkerList()
        })
@@ -62,6 +65,7 @@ var _ = Describe("WorkerList", func() {
 
        Describe("Register", func() {
                var registeredWorkers []string
+               invalidAddr := "addr.invalid"
 
                BeforeEach(func() {
                        registeredWorkers = make([]string, 0)
@@ -99,6 +103,23 @@ var _ = Describe("WorkerList", func() {
                        }
                }
 
+               DescribeTable("dryad and sshd addresses",
+                       func(dryadAddress, sshAddress string, errMatcher types.GomegaMatcher) {
+                               caps := getRandomCaps()
+                               err := wl.Register(caps, dryadAddress, sshAddress)
+                               Expect(err).To(errMatcher)
+                       },
+                       Entry("both addresses missing", "", "", Equal(ErrMissingIP)),
+                       Entry("sshd address missing", dryadAddr.String(), "", Equal(ErrMissingIP)),
+                       Entry("dryad address missing", "", sshdAddr.String(), Equal(ErrMissingIP)),
+                       Entry("dryad port missing", missingPort.String(), sshdAddr.String(), Equal(ErrMissingPort)),
+                       Entry("sshd port missing", dryadAddr.String(), missingPort.String(), Equal(ErrMissingPort)),
+                       Entry("both ports missing", missingPort.String(), missingPort.String(), Equal(ErrMissingPort)),
+                       Entry("both invalid", invalidAddr, invalidAddr, HaveOccurred()),
+                       Entry("dryad invalid", invalidAddr, sshdAddr.String(), HaveOccurred()),
+                       Entry("sshd invalid", dryadAddr.String(), invalidAddr, HaveOccurred()),
+               )
+
                It("should add Worker in MAINTENANCE state", func() {
                        caps := getRandomCaps()
                        err := wl.Register(caps, dryadAddr.String(), sshdAddr.String())
@@ -368,7 +389,7 @@ var _ = Describe("WorkerList", func() {
 
                                        It("should work to SetState", func() {
                                                gomock.InOrder(
-                                                       dcm.EXPECT().Create(ip, conf.DefaultRPCPort),
+                                                       dcm.EXPECT().Create(info.dryad),
                                                        dcm.EXPECT().Prepare().Return(key, nil),
                                                        dcm.EXPECT().Close(),
                                                )
@@ -381,7 +402,7 @@ var _ = Describe("WorkerList", func() {
 
                                        It("should fail to SetState if dryadClientManager fails to prepare client", func() {
                                                gomock.InOrder(
-                                                       dcm.EXPECT().Create(ip, conf.DefaultRPCPort),
+                                                       dcm.EXPECT().Create(info.dryad),
                                                        dcm.EXPECT().Prepare().Return(nil, testerr),
                                                        dcm.EXPECT().Close(),
                                                )
@@ -393,7 +414,7 @@ var _ = Describe("WorkerList", func() {
                                        })
 
                                        It("should fail to SetState if dryadClientManager fails to create client", func() {
-                                               dcm.EXPECT().Create(ip, conf.DefaultRPCPort).Return(testerr)
+                                               dcm.EXPECT().Create(info.dryad).Return(testerr)
 
                                                err := wl.SetState(worker, IDLE)
                                                Expect(err).ToNot(HaveOccurred())
@@ -422,7 +443,7 @@ var _ = Describe("WorkerList", func() {
 
                                                It("should work to SetState", func() {
                                                        gomock.InOrder(
-                                                               dcm.EXPECT().Create(ip, conf.DefaultRPCPort),
+                                                               dcm.EXPECT().Create(info.dryad),
                                                                dcm.EXPECT().PutInMaintenance(putStr),
                                                                dcm.EXPECT().Close(),
                                                        )
@@ -434,7 +455,7 @@ var _ = Describe("WorkerList", func() {
 
                                                It("should fail to SetState if dryadClientManager fails to put dryad in maintenance state", func() {
                                                        gomock.InOrder(
-                                                               dcm.EXPECT().Create(ip, conf.DefaultRPCPort),
+                                                               dcm.EXPECT().Create(info.dryad),
                                                                dcm.EXPECT().PutInMaintenance(putStr).Return(testerr),
                                                                dcm.EXPECT().Close().Do(func() {
                                                                        wl.mutex.Lock()
@@ -451,7 +472,7 @@ var _ = Describe("WorkerList", func() {
                                                })
 
                                                It("should fail to SetState if dryadClientManager fails to create client", func() {
-                                                       dcm.EXPECT().Create(ip, conf.DefaultRPCPort).Return(testerr).Do(func(net.IP, int) {
+                                                       dcm.EXPECT().Create(info.dryad).Return(testerr).Do(func(*net.TCPAddr) {
                                                                wl.mutex.Lock()
                                                                info.State = WorkerState("TEST")
                                                                wl.mutex.Unlock()
@@ -468,7 +489,7 @@ var _ = Describe("WorkerList", func() {
                                Describe("putInMaintenance", func() {
                                        It("should work", func() {
                                                gomock.InOrder(
-                                                       dcm.EXPECT().Create(ip, conf.DefaultRPCPort),
+                                                       dcm.EXPECT().Create(info.dryad),
                                                        dcm.EXPECT().PutInMaintenance(putStr),
                                                        dcm.EXPECT().Close(),
                                                )
@@ -479,7 +500,7 @@ var _ = Describe("WorkerList", func() {
 
                                        It("should fail if dryadClientManager fails to put dryad in maintenance state", func() {
                                                gomock.InOrder(
-                                                       dcm.EXPECT().Create(ip, conf.DefaultRPCPort),
+                                                       dcm.EXPECT().Create(info.dryad),
                                                        dcm.EXPECT().PutInMaintenance(putStr).Return(testerr),
                                                        dcm.EXPECT().Close(),
                                                )
@@ -489,7 +510,7 @@ var _ = Describe("WorkerList", func() {
                                        })
 
                                        It("should fail if dryadClientManager fails to create client", func() {
-                                               dcm.EXPECT().Create(ip, conf.DefaultRPCPort).Return(testerr)
+                                               dcm.EXPECT().Create(info.dryad).Return(testerr)
 
                                                err := wl.putInMaintenance(worker)
                                                Expect(err).To(Equal(testerr))
@@ -702,38 +723,38 @@ var _ = Describe("WorkerList", func() {
 
                Describe("Setters and Getters", func() {
                        type genericGet func(wl *WorkerList, uuid WorkerUUID, expectedItem interface{}, expectedErr error)
-                       getIP := genericGet(func(wl *WorkerList, uuid WorkerUUID, expectedItem interface{}, expectedErr error) {
-                               item, err := wl.GetWorkerIP(uuid)
+                       getDryad := genericGet(func(wl *WorkerList, uuid WorkerUUID, expectedItem interface{}, expectedErr error) {
+                               item, err := wl.GetWorkerAddr(uuid)
                                if expectedErr != nil {
-                                       Expect(item).To(BeNil())
+                                       Expect(item).To(Equal(net.TCPAddr{}))
                                        Expect(err).To(Equal(expectedErr))
                                        return
                                }
                                Expect(err).ToNot(HaveOccurred())
-                               Expect(item).To(Equal(expectedItem.(net.IP)))
+                               Expect(item).To(Equal(expectedItem.(net.TCPAddr)))
                        })
-                       getKey := genericGet(func(wl *WorkerList, uuid WorkerUUID, expectedItem interface{}, expectedErr error) {
-                               item, err := wl.GetWorkerKey(uuid)
+                       getSSH := genericGet(func(wl *WorkerList, uuid WorkerUUID, expectedItem interface{}, expectedErr error) {
+                               item, err := wl.GetWorkerSSHAddr(uuid)
                                if expectedErr != nil {
+                                       Expect(item).To(Equal(net.TCPAddr{}))
                                        Expect(err).To(Equal(expectedErr))
                                        return
                                }
                                Expect(err).ToNot(HaveOccurred())
-                               Expect(&item).To(Equal(expectedItem.(*rsa.PrivateKey)))
+                               Expect(item).To(Equal(expectedItem.(net.TCPAddr)))
                        })
-                       getters := []genericGet{getIP, getKey}
-
-                       type genericSet func(wl *WorkerList, uuid WorkerUUID, expectedErr error) interface{}
-                       setIP := genericSet(func(wl *WorkerList, uuid WorkerUUID, expectedErr error) interface{} {
-                               ip := net.IP{255, 255, 255, 255}
-                               err := wl.SetWorkerIP(uuid, ip)
+                       getKey := genericGet(func(wl *WorkerList, uuid WorkerUUID, expectedItem interface{}, expectedErr error) {
+                               item, err := wl.GetWorkerKey(uuid)
                                if expectedErr != nil {
                                        Expect(err).To(Equal(expectedErr))
-                                       return nil
+                                       return
                                }
                                Expect(err).ToNot(HaveOccurred())
-                               return ip
+                               Expect(&item).To(Equal(expectedItem.(*rsa.PrivateKey)))
                        })
+                       getters := []genericGet{getKey, getDryad, getSSH}
+
+                       type genericSet func(wl *WorkerList, uuid WorkerUUID, expectedErr error) interface{}
                        setKey := genericSet(func(wl *WorkerList, uuid WorkerUUID, expectedErr error) interface{} {
                                key, err := rsa.GenerateKey(rand.Reader, 128)
                                Expect(err).ToNot(HaveOccurred())
@@ -745,7 +766,7 @@ var _ = Describe("WorkerList", func() {
                                Expect(err).ToNot(HaveOccurred())
                                return key
                        })
-                       setters := []genericSet{setIP, setKey}
+                       setters := []genericSet{setKey}
 
                        It("should fail to get information of nonexistent worker", func() {
                                uuid := randomUUID()
@@ -832,7 +853,7 @@ var _ = Describe("WorkerList", func() {
                                })
                                It("should set worker into IDLE state and prepare a key", func() {
                                        gomock.InOrder(
-                                               dcm.EXPECT().Create(ip, conf.DefaultRPCPort),
+                                               dcm.EXPECT().Create(info.dryad),
                                                dcm.EXPECT().Prepare().Return(key, nil),
                                                dcm.EXPECT().Close(),
                                        )
@@ -845,7 +866,7 @@ var _ = Describe("WorkerList", func() {
                                })
                                It("should fail to prepare worker if dryadClientManager fails to prepare client", func() {
                                        gomock.InOrder(
-                                               dcm.EXPECT().Create(ip, conf.DefaultRPCPort),
+                                               dcm.EXPECT().Create(info.dryad),
                                                dcm.EXPECT().Prepare().Return(nil, testerr),
                                                dcm.EXPECT().Close(),
                                        )
@@ -857,7 +878,7 @@ var _ = Describe("WorkerList", func() {
                                        Expect(info.key).To(BeNil())
                                })
                                It("should fail to prepare worker if dryadClientManager fails to create client", func() {
-                                       dcm.EXPECT().Create(ip, conf.DefaultRPCPort).Return(testerr)
+                                       dcm.EXPECT().Create(info.dryad).Return(testerr)
 
                                        err := wl.PrepareWorker(worker, true)
                                        Expect(err).NotTo(HaveOccurred())
index 6e3dd7c..da22336 100644 (file)
@@ -19,13 +19,12 @@ package workers
 
 import (
        "crypto/rsa"
-       "errors"
+       "fmt"
        "math"
        "net"
        "sync"
 
        . "git.tizen.org/tools/boruta"
-       "git.tizen.org/tools/boruta/dryad/conf"
        "git.tizen.org/tools/boruta/rpc/dryad"
 )
 
@@ -88,19 +87,26 @@ func (wl *WorkerList) Register(caps Capabilities, dryadAddress string, sshAddres
 
        dryad, err := net.ResolveTCPAddr("tcp", dryadAddress)
        if err != nil {
-               return err
+               return fmt.Errorf("invalid dryad address: %s", err)
        }
        // dryad.IP is empty if dryadAddress provided port number only.
        if dryad.IP == nil {
-               return errors.New("missing IP in dryad address")
+               return ErrMissingIP
+       }
+       if dryad.Port == 0 {
+               return ErrMissingPort
        }
+
        sshd, err := net.ResolveTCPAddr("tcp", sshAddress)
        if err != nil {
-               return err
+               return fmt.Errorf("invalid sshd address: %s", err)
        }
        // same as with dryad.IP
        if sshd.IP == nil {
-               return errors.New("missing IP in ssh address")
+               return ErrMissingIP
+       }
+       if sshd.Port == 0 {
+               return ErrMissingPort
        }
 
        wl.mutex.Lock()
@@ -283,30 +289,26 @@ func (wl *WorkerList) GetWorkerInfo(uuid WorkerUUID) (WorkerInfo, error) {
        return worker.WorkerInfo, nil
 }
 
-// SetWorkerIP stores ip in the worker structure referenced by uuid.
-// It should be called after Register by function which is aware of
-// the source of the connection and therefore its IP address.
-func (wl *WorkerList) SetWorkerIP(uuid WorkerUUID, ip net.IP) error {
-       wl.mutex.Lock()
-       defer wl.mutex.Unlock()
+// GetWorkerAddr retrieves IP address from the internal structure.
+func (wl *WorkerList) GetWorkerAddr(uuid WorkerUUID) (net.TCPAddr, error) {
+       wl.mutex.RLock()
+       defer wl.mutex.RUnlock()
        worker, ok := wl.workers[uuid]
        if !ok {
-               return ErrWorkerNotFound
+               return net.TCPAddr{}, ErrWorkerNotFound
        }
-       // FIXME
-       worker.dryad.IP = ip
-       return nil
+       return *worker.dryad, nil
 }
 
-// GetWorkerIP retrieves IP address from the internal structure.
-func (wl *WorkerList) GetWorkerIP(uuid WorkerUUID) (net.IP, error) {
+// GetWorkerSSHAddr retrieves address of worker's ssh daemon from the internal structure.
+func (wl *WorkerList) GetWorkerSSHAddr(uuid WorkerUUID) (net.TCPAddr, error) {
        wl.mutex.RLock()
        defer wl.mutex.RUnlock()
        worker, ok := wl.workers[uuid]
        if !ok {
-               return nil, ErrWorkerNotFound
+               return net.TCPAddr{}, ErrWorkerNotFound
        }
-       return worker.dryad.IP, nil
+       return *worker.sshd, nil
 }
 
 // SetWorkerKey stores private key in the worker structure referenced by uuid.
@@ -441,12 +443,12 @@ func (wl *WorkerList) setState(worker WorkerUUID, state WorkerState) error {
 // prepareKey delegates key generation to Dryad and sets up generated key in the
 // worker. In case of any failure it returns an error.
 func (wl *WorkerList) prepareKey(worker WorkerUUID) error {
-       ip, err := wl.GetWorkerIP(worker)
+       addr, err := wl.GetWorkerAddr(worker)
        if err != nil {
                return err
        }
        client := wl.newDryadClient()
-       err = client.Create(ip, conf.DefaultRPCPort)
+       err = client.Create(&addr)
        if err != nil {
                return err
        }
@@ -461,12 +463,12 @@ func (wl *WorkerList) prepareKey(worker WorkerUUID) error {
 
 // putInMaintenance orders Dryad to enter maintenance mode.
 func (wl *WorkerList) putInMaintenance(worker WorkerUUID) error {
-       ip, err := wl.GetWorkerIP(worker)
+       addr, err := wl.GetWorkerAddr(worker)
        if err != nil {
                return err
        }
        client := wl.newDryadClient()
-       err = client.Create(ip, conf.DefaultRPCPort)
+       err = client.Create(&addr)
        if err != nil {
                return err
        }