Skip to content

Commit

Permalink
Added some proxy unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
eko committed Jul 21, 2019
1 parent fff4eb4 commit e390ac7
Show file tree
Hide file tree
Showing 15 changed files with 227 additions and 63 deletions.
9 changes: 5 additions & 4 deletions Makefile
Expand Up @@ -10,10 +10,11 @@ generate-mocks: ## Generate mocks for tests
@echo "> generating mocks..."

# Monday
mockery -name=ProxyInterface -dir=pkg/proxy/ -output internal/tests/mocks
mockery -name=RunnerInterface -dir=pkg/runner/ -output internal/tests/mocks
mockery -name=ForwarderInterface -dir=pkg/forwarder/ -output internal/tests/mocks
mockery -name=WatcherInterface -dir=pkg/watcher/ -output internal/tests/mocks
mockery -name=HostfileInterface -dir=pkg/hostfile/ -output internal/tests/mocks/hostfile
mockery -name=ProxyInterface -dir=pkg/proxy/ -output internal/tests/mocks/proxy
mockery -name=RunnerInterface -dir=pkg/runner/ -output internal/tests/mocks/runner
mockery -name=ForwarderInterface -dir=pkg/forwarder/ -output internal/tests/mocks/forwarder
mockery -name=WatcherInterface -dir=pkg/watcher/ -output internal/tests/mocks/watcher

# Kubernetes AppsV1
mockery -name=Interface -dir=vendor/k8s.io/client-go/kubernetes/ -output internal/tests/mocks/kubernetes/client
Expand Down
9 changes: 8 additions & 1 deletion cmd/main.go
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/eko/monday/internal/config"
"github.com/eko/monday/pkg/forwarder"
"github.com/eko/monday/pkg/hostfile"
"github.com/eko/monday/pkg/proxy"
"github.com/eko/monday/pkg/runner"
"github.com/eko/monday/pkg/watcher"
Expand Down Expand Up @@ -79,8 +80,14 @@ func run(conf *config.Config, choice string) {
panic(err)
}

// Initializes hosts file manager
hostfile, err := hostfile.NewClient()
if err != nil {
panic(err)
}

// Initializes proxy
proxyComponent = proxy.NewProxy()
proxyComponent = proxy.NewProxy(hostfile)

// Initializes runner
runnerComponent = runner.NewRunner(proxyComponent, project)
Expand Down
File renamed without changes.
38 changes: 38 additions & 0 deletions internal/tests/mocks/hostfile/HostfileInterface.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion pkg/forwarder/forwarder_test.go
Expand Up @@ -5,7 +5,7 @@ import (
"testing"

"github.com/eko/monday/internal/config"
"github.com/eko/monday/internal/tests/mocks"
mocks "github.com/eko/monday/internal/tests/mocks/proxy"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
Expand Down
46 changes: 46 additions & 0 deletions pkg/hostfile/client.go
@@ -0,0 +1,46 @@
package hostfile

import "github.com/txn2/txeh"

type HostfileInterface interface {
AddHost(ip, hostname string) error
RemoveHost(hostname string) error
}

// Hostfile represents the host file manager client
type Hostfile struct {
hosts *txeh.Hosts
}

// NewClient returns a new Hostfile manager client
func NewClient() (*Hostfile, error) {
hosts, err := txeh.NewHostsDefault()
if err != nil {
panic(err)
}

return &Hostfile{
hosts: hosts,
}, err
}

// AddHost adds a new host / ip entry into the hosts file
func (h *Hostfile) AddHost(ip, hostname string) error {
h.hosts.Reload()
h.hosts.AddHost(ip, hostname)
err := h.hosts.Save()
if err != nil {
return err
}

return nil
}

// RemoveHost removes a given hostname from the hosts file
func (h *Hostfile) RemoveHost(hostname string) error {
h.hosts.Reload()
h.hosts.RemoveHost(hostname)
h.hosts.Save()

return nil
}
42 changes: 0 additions & 42 deletions pkg/hostfile/hostfile.go

This file was deleted.

15 changes: 12 additions & 3 deletions pkg/proxy/proxy.go
Expand Up @@ -11,6 +11,8 @@ import (
)

const (
// ProxyPortStart is the first port that will be allocated by the proxy component.
// Others will be incremented by 1 each time
ProxyPortStart = "9400"
)

Expand All @@ -20,8 +22,10 @@ type ProxyInterface interface {
AddProxyForward(name string, proxyForward *ProxyForward)
}

// Proxy represents the proxy component instance
type Proxy struct {
ProxyForwards map[string][]*ProxyForward
hostfile hostfile.HostfileInterface
listeners map[string]net.Listener
listening bool
addProxyForwardMux sync.Mutex
Expand All @@ -31,9 +35,11 @@ type Proxy struct {
ipLastByte int
}

func NewProxy() *Proxy {
// NewProxy initializes a new proxy component instance
func NewProxy(hostfile hostfile.HostfileInterface) *Proxy {
return &Proxy{
ProxyForwards: make(map[string][]*ProxyForward, 0),
hostfile: hostfile,
listeners: make(map[string]net.Listener),
listening: true,
latestPort: ProxyPortStart,
Expand Down Expand Up @@ -125,13 +131,16 @@ func (p *Proxy) AddProxyForward(name string, proxyForward *ProxyForward) {
p.addProxyForwardMux.Lock()
defer p.addProxyForwardMux.Unlock()

p.generateIP(proxyForward)
err := p.generateIP(proxyForward)
if err != nil {
fmt.Printf("❌ An error has occured while generating IP address for '%s': %v\n", proxyForward.Name, err)
}

if proxyForward.ProxyPort == "" {
p.generateProxyPort(proxyForward)
}

err := hostfile.AddHost(proxyForward.LocalIP, proxyForward.GetHostname())
err = p.hostfile.AddHost(proxyForward.LocalIP, proxyForward.GetHostname())
if err != nil {
fmt.Printf("❌ An error has occured while trying to write host file for application '%s' (ip: %s): %v\n", proxyForward.Name, proxyForward.LocalIP, err)
}
Expand Down
6 changes: 6 additions & 0 deletions pkg/proxy/proxy_forward.go
Expand Up @@ -12,6 +12,7 @@ type ProxyForward struct {
ProxyPort string
}

// NewProxyForward returns a new proxy port-forward instance
func NewProxyForward(name, hostname, proxyHostname, localPort, forwardPort string) *ProxyForward {
proxyForward := &ProxyForward{
Name: name,
Expand All @@ -30,18 +31,23 @@ func NewProxyForward(name, hostname, proxyHostname, localPort, forwardPort strin
return proxyForward
}

// SetLocalIP sets local attributed IP to this forward
func (p *ProxyForward) SetLocalIP(ip string) {
p.LocalIP = ip
}

// SetProxyPort sets proxy attributed port to this forward
func (p *ProxyForward) SetProxyPort(port string) {
p.ProxyPort = port
}

// GetProxifiedPorts returns the couple of proxified ports (proxy attributed port:forward port)
func (p *ProxyForward) GetProxifiedPorts() string {
return fmt.Sprintf("%s:%s", p.ProxyPort, p.ForwardPort)
}

// GetHostname returns the hostname (if defined) of this proxy forward, elsewhere uses the
// service name
func (p *ProxyForward) GetHostname() string {
if p.Hostname != "" {
return p.Hostname
Expand Down
102 changes: 100 additions & 2 deletions pkg/proxy/proxy_test.go
Expand Up @@ -3,16 +3,114 @@ package proxy
import (
"testing"

mocks "github.com/eko/monday/internal/tests/mocks/hostfile"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)

func TestNewProxy(t *testing.T) {
// Given

hostfileMock := &mocks.HostfileInterface{}

// When
proxy := NewProxy()
proxy := NewProxy(hostfileMock)

// Then
assert.IsType(t, new(Proxy), proxy)

assert.Len(t, proxy.ProxyForwards, 0)
assert.Len(t, proxy.attributedIPs, 0)
assert.Equal(t, proxy.latestPort, "9400")
assert.Equal(t, proxy.ipLastByte, 1)
}

func TestAddProxyForward(t *testing.T) {
// Given
pf := NewProxyForward("test", "hostname.svc.local", "", "8080", "8080")

hostfileMock := &mocks.HostfileInterface{}
hostfileMock.On("AddHost", mock.AnythingOfType("string"), "hostname.svc.local").Return(nil)

proxy := NewProxy(hostfileMock)

// When
proxy.AddProxyForward("test", pf)

// Then
assert.Len(t, proxy.ProxyForwards, 1)
assert.Equal(t, proxy.latestPort, "9401")
assert.Equal(t, proxy.ipLastByte, 2)
}

func TestAddProxyForwardWhenMultiple(t *testing.T) {
// Given
testCases := []struct {
name string
hostname string
localPort string
forwardPort string
}{
{name: "test", hostname: "hostname.svc.local", localPort: "8080", forwardPort: "8081"},
{name: "test-2", hostname: "hostname2.svc.local", localPort: "8080", forwardPort: "8081"},
{name: "test-2", hostname: "hostname3.svc.local", localPort: "8081", forwardPort: "8082"},
}

hostfileMock := &mocks.HostfileInterface{}
hostfileMock.ExpectedCalls = []*mock.Call{
&mock.Call{
Method: "AddHost",
Arguments: mock.Arguments{
mock.AnythingOfType("string"), "hostname.svc.local",
},
ReturnArguments: mock.Arguments{nil},
},
&mock.Call{
Method: "AddHost",
Arguments: mock.Arguments{
mock.AnythingOfType("string"), "hostname2.svc.local",
},
ReturnArguments: mock.Arguments{nil},
},
&mock.Call{
Method: "AddHost",
Arguments: mock.Arguments{
mock.AnythingOfType("string"), "hostname3.svc.local",
},
ReturnArguments: mock.Arguments{nil},
},
}

proxy := NewProxy(hostfileMock)

// When
for _, testCase := range testCases {
pf := NewProxyForward(testCase.name, testCase.hostname, "", testCase.localPort, testCase.forwardPort)
proxy.AddProxyForward(testCase.name, pf)
}

// Then
assert.Len(t, proxy.ProxyForwards, 2)
assert.Equal(t, proxy.latestPort, "9403")
assert.Equal(t, proxy.ipLastByte, 3)
}

func TestListen(t *testing.T) {
// Given
pf := NewProxyForward("test", "hostname.svc.local", "", "8080", "8080")

hostfileMock := &mocks.HostfileInterface{}
hostfileMock.On("AddHost", mock.AnythingOfType("string"), "hostname.svc.local").Return(nil)

proxy := NewProxy(hostfileMock)
proxy.AddProxyForward("test", pf)

// When
err := proxy.Listen()

// Then
assert.Nil(t, err)

assert.Len(t, proxy.ProxyForwards, 1)
assert.Equal(t, proxy.latestPort, "9401")
assert.Equal(t, proxy.ipLastByte, 2)
}
2 changes: 1 addition & 1 deletion pkg/runner/runner_test.go
Expand Up @@ -7,7 +7,7 @@ import (
"time"

"github.com/eko/monday/internal/config"
"github.com/eko/monday/internal/tests/mocks"
mocks "github.com/eko/monday/internal/tests/mocks/proxy"
"github.com/stretchr/testify/assert"
)

Expand Down

0 comments on commit e390ac7

Please sign in to comment.