Skip to content

Commit

Permalink
endpoint: move TestReadEpsFromDirNames to pkg/endpoint
Browse files Browse the repository at this point in the history
The test was previously in `daemon`, and necessitated leaking a lot of
Endpoint-related state. Instead, refactor the test into the Endpoint package.
Do not regenerate the endpoints needed for testing; instead, write their
headerfiles using `writeHeaderfile`, since that is the operation which
is needed to be performed in order to perform the test to read the serialized
Endpoints from their corresponding headerfiles.

Signed-off by: Ian Vernon <ian@cilium.io>
  • Loading branch information
Ian Vernon committed Aug 22, 2019
1 parent af710fd commit 852d91d
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 131 deletions.
28 changes: 25 additions & 3 deletions pkg/endpoint/endpoint_test.go
Expand Up @@ -19,6 +19,7 @@ package endpoint
import (
"context"
"reflect"
"sync"
"testing"
"time"

Expand All @@ -28,13 +29,14 @@ import (
"github.com/cilium/cilium/pkg/endpoint/regeneration"
"github.com/cilium/cilium/pkg/identity"
"github.com/cilium/cilium/pkg/identity/cache"
"github.com/cilium/cilium/pkg/k8s/apis/cilium.io"
ciliumio "github.com/cilium/cilium/pkg/k8s/apis/cilium.io"
"github.com/cilium/cilium/pkg/kvstore"
pkgLabels "github.com/cilium/cilium/pkg/labels"
"github.com/cilium/cilium/pkg/lock"
monitorAPI "github.com/cilium/cilium/pkg/monitor/api"
"github.com/cilium/cilium/pkg/policy"
"github.com/cilium/cilium/pkg/policy/api"
"github.com/cilium/cilium/pkg/proxy/accesslog"
"github.com/cilium/cilium/pkg/revert"

. "gopkg.in/check.v1"
Expand All @@ -49,7 +51,27 @@ var (
func Test(t *testing.T) { TestingT(t) }

type EndpointSuite struct {
repo *policy.Repository
regeneration.Owner
repo *policy.Repository
compilationMutex *lock.RWMutex
datapath datapath.Datapath

// Owners interface mock
OnTracingEnabled func() bool
OnAlwaysAllowLocalhost func() bool
OnGetCachedLabelList func(id identity.NumericIdentity) (pkgLabels.LabelArray, error)
OnGetPolicyRepository func() *policy.Repository
OnUpdateProxyRedirect func(e regeneration.EndpointUpdater, l4 *policy.L4Filter, proxyWaitGroup *completion.WaitGroup) (uint16, error, revert.FinalizeFunc, revert.RevertFunc)
OnRemoveProxyRedirect func(e regeneration.EndpointInfoSource, id string, proxyWaitGroup *completion.WaitGroup) (error, revert.FinalizeFunc, revert.RevertFunc)
OnUpdateNetworkPolicy func(e regeneration.EndpointUpdater, policy *policy.L4Policy, proxyWaitGroup *completion.WaitGroup) (error, revert.RevertFunc)
OnRemoveNetworkPolicy func(e regeneration.EndpointInfoSource)
OnQueueEndpointBuild func(ctx context.Context, epID uint64) (func(), error)
OnRemoveFromEndpointQueue func(epID uint64)
OnDebugEnabled func() bool
OnGetCompilationLock func() *lock.RWMutex
OnSendNotification func(typ monitorAPI.AgentNotification, text string) error
OnNewProxyLogRecord func(l *accesslog.LogRecord) error
OnClearPolicyConsumers func(id uint16) *sync.WaitGroup
}

// suite can be used by testing.T benchmarks or tests as a mock regeneration.Owner
Expand Down Expand Up @@ -94,7 +116,7 @@ func (s *EndpointSuite) SendNotification(typ monitorAPI.AgentNotification, text
}

func (s *EndpointSuite) Datapath() datapath.Datapath {
return nil
return s.datapath
}

func (s *EndpointSuite) GetNodeSuffix() string {
Expand Down
169 changes: 41 additions & 128 deletions daemon/state_test.go → pkg/endpoint/restore_test.go
Expand Up @@ -14,46 +14,35 @@

// +build !privileged_tests

package main
package endpoint

import (
"context"
"encoding/binary"
"fmt"
"io/ioutil"
"net"
"os"
"path/filepath"
"sort"
"sync"

"github.com/cilium/cilium/common/addressing"
"github.com/cilium/cilium/pkg/checker"
"github.com/cilium/cilium/pkg/completion"
linuxDatapath "github.com/cilium/cilium/pkg/datapath/linux"
e "github.com/cilium/cilium/pkg/endpoint"
"github.com/cilium/cilium/pkg/endpoint/regeneration"
"github.com/cilium/cilium/pkg/identity"
"github.com/cilium/cilium/pkg/identity/identitymanager"
"github.com/cilium/cilium/pkg/labels"
"github.com/cilium/cilium/pkg/lock"
"github.com/cilium/cilium/pkg/mac"
monitorAPI "github.com/cilium/cilium/pkg/monitor/api"
"github.com/cilium/cilium/pkg/option"
"github.com/cilium/cilium/pkg/policy"
"github.com/cilium/cilium/pkg/revert"

. "gopkg.in/check.v1"
)

func (ds *DaemonSuite) createEndpoints() ([]*e.Endpoint, map[uint16]*e.Endpoint) {
epsWanted := []*e.Endpoint{
func (ds *EndpointSuite) createEndpoints() ([]*Endpoint, map[uint16]*Endpoint) {
epsWanted := []*Endpoint{
ds.endpointCreator(256, identity.NumericIdentity(1256)),
ds.endpointCreator(257, identity.NumericIdentity(1257)),
ds.endpointCreator(258, identity.NumericIdentity(1258)),
ds.endpointCreator(259, identity.NumericIdentity(1259)),
}
epsMap := map[uint16]*e.Endpoint{
epsMap := map[uint16]*Endpoint{
epsWanted[0].ID: epsWanted[0],
epsWanted[1].ID: epsWanted[1],
epsWanted[2].ID: epsWanted[2],
Expand All @@ -66,7 +55,7 @@ func getStrID(id uint16) string {
return fmt.Sprintf("%05d", id)
}

func (ds *DaemonSuite) endpointCreator(id uint16, secID identity.NumericIdentity) *e.Endpoint {
func (ds *EndpointSuite) endpointCreator(id uint16, secID identity.NumericIdentity) *Endpoint {
strID := getStrID(id)
b := make([]byte, 2)
binary.LittleEndian.PutUint16(b, id)
Expand All @@ -79,10 +68,10 @@ func (ds *DaemonSuite) endpointCreator(id uint16, secID identity.NumericIdentity
}
identity.Sanitize()

repo := ds.d.GetPolicyRepository()
repo := ds.GetPolicyRepository()
repo.GetPolicyCache().LocalEndpointIdentityAdded(identity)

ep := e.NewEndpointWithState(ds.d, id, e.StateReady)
ep := NewEndpointWithState(ds, id, StateReady)
// Random network ID and docker endpoint ID with 59 hex chars + 5 strID = 64 hex chars
ep.DockerNetworkID = "603e047d2268a57f5a5f93f7f9e1263e9207e348a06654bf64948def001" + strID
ep.DockerEndpointID = "93529fda8c401a071d21d6bd46fdf5499b9014dcb5a35f2e3efaa8d8002" + strID
Expand All @@ -97,142 +86,66 @@ func (ds *DaemonSuite) endpointCreator(id uint16, secID identity.NumericIdentity
return ep
}

// generateEPs is a helper function to create dummy endpoints in the given
// baseDirectory. This function regenerates the endpoints and creates the bpf
// and header files in the endpoint's directory
func (ds *DaemonSuite) generateEPs(baseDir string, epsWanted []*e.Endpoint, epsMap map[uint16]*e.Endpoint) ([]string, error) {
var err error
var (
regenerationMetadata = &regeneration.ExternalRegenerationMetadata{
Reason: "test",
}
)

func (ds *EndpointSuite) TestReadEPsFromDirNames(c *C) {
// For this test, the real linux datapath is necessary to properly
// serialize config files to disk and test the restore.
oldDatapath := ds.datapath
defer func() {
if err != nil {
os.RemoveAll(baseDir)
}
ds.datapath = oldDatapath
}()
ds.datapath = linuxDatapath.NewDatapath(linuxDatapath.DatapathConfiguration{}, nil)

ds.d.compilationMutex = new(lock.RWMutex)

builders := 0
epsWanted, _ := ds.createEndpoints()
tmpDir, err := ioutil.TempDir("", "cilium-tests")
defer func() {
if builders != 0 {
log.Fatal("Endpoint Build Queue leaks")
}
os.RemoveAll(tmpDir)
}()

ds.OnQueueEndpointBuild = func(ctx context.Context, epID uint64) (func(), error) {
builders++
var once sync.Once
doneFunc := func() {
once.Do(func() {
builders--
})
}
return doneFunc, nil
}

ds.OnTracingEnabled = func() bool {
return false
}
ds.OnGetPolicyRepository = func() *policy.Repository {
return ds.d.GetPolicyRepository()
}
ds.OnAlwaysAllowLocalhost = func() bool {
return false
}

ds.OnGetCompilationLock = func() *lock.RWMutex {
return ds.d.compilationMutex
}

ds.OnSendNotification = func(typ monitorAPI.AgentNotification, text string) error {
return nil
}

ds.OnUpdateNetworkPolicy = func(e regeneration.EndpointUpdater, policy *policy.L4Policy,
proxyWaitGroup *completion.WaitGroup) (error, revert.RevertFunc) {
return nil, nil
}

ds.OnRemoveNetworkPolicy = func(e regeneration.EndpointInfoSource) {}

// Since all owner's funcs are implemented we can regenerate every endpoint.
os.Chdir(tmpDir)
c.Assert(err, IsNil)
epsNames := []string{}
c.Assert(err, IsNil)
for _, ep := range epsWanted {
fullDirName := filepath.Join(baseDir, ep.DirectoryPath())
os.MkdirAll(fullDirName, 777)
ep.UnconditionalLock()

// The identities must be tracked in identitymanager to
// regenerate the policy for them.
identitymanager.Add(ep.SecurityIdentity)
defer identitymanager.Remove(ep.SecurityIdentity)

ready := ep.SetStateLocked(e.StateWaitingToRegenerate, "test")
ep.Unlock()
if ready {
<-ep.Regenerate(regenerationMetadata)
}
c.Assert(ep, NotNil)

fullDirName := filepath.Join(tmpDir, ep.DirectoryPath())
err := os.MkdirAll(fullDirName, 0777)
c.Assert(err, IsNil)

err = ep.writeHeaderfile(fullDirName)
c.Assert(err, IsNil)

switch ep.ID {
case 256, 257:
err := os.Rename(fullDirName, filepath.Join(baseDir, ep.FailedDirectoryPath()))
if err != nil {
return nil, err
}
failedDir := filepath.Join(tmpDir, ep.FailedDirectoryPath())
err := os.Rename(fullDirName, failedDir)
c.Assert(err, IsNil)
epsNames = append(epsNames, ep.FailedDirectoryPath())

// create one failed and the other non failed directory for ep 256.
if ep.ID == 256 {
fullDirName := filepath.Join(baseDir, ep.DirectoryPath())
os.MkdirAll(fullDirName, 777)

ep.UnconditionalLock()
// Change endpoint a little bit so we know which endpoint is in
// "256_next_fail" and with one is in the "256" directory.
ep.SetNodeMACLocked(mac.MAC([]byte{0x02, 0xff, 0xf2, 0x12, 0xc1, 0xc1}))
ready := ep.SetStateLocked(e.StateWaitingToRegenerate, "test")
ep.Unlock()
if ready {
<-ep.Regenerate(regenerationMetadata)
}
ep.NodeMAC = []byte{0x02, 0xff, 0xf2, 0x12, 0xc1, 0xc1}
err = ep.writeHeaderfile(failedDir)
c.Assert(err, IsNil)
epsNames = append(epsNames, ep.DirectoryPath())
}
default:
epsNames = append(epsNames, ep.DirectoryPath())
}
}
return epsNames, nil
}

func (ds *DaemonSuite) TestReadEPsFromDirNames(c *C) {
// For this test, the real linux datapath is necessary to properly
// serialize config files to disk and test the restore.
oldDatapath := ds.d.datapath
defer func() {
ds.d.datapath = oldDatapath
}()
ds.d.datapath = linuxDatapath.NewDatapath(linuxDatapath.DatapathConfiguration{}, nil)

epsWanted, epsMap := ds.createEndpoints()
tmpDir, err := ioutil.TempDir("", "cilium-tests")
defer func() {
os.RemoveAll(tmpDir)
}()

os.Chdir(tmpDir)

oldStateDir := option.Config.StateDir
option.Config.StateDir = tmpDir
defer func() {
os.Chdir(oldStateDir)
option.Config.StateDir = oldStateDir
}()
c.Assert(err, IsNil)
epsNames, err := ds.generateEPs(tmpDir, epsWanted, epsMap)
c.Assert(err, IsNil)
eps := e.ReadEPsFromDirNames(ds.d, tmpDir, epsNames)
eps := ReadEPsFromDirNames(ds, tmpDir, epsNames)
c.Assert(len(eps), Equals, len(epsWanted))

sort.Slice(epsWanted, func(i, j int) bool { return epsWanted[i].ID < epsWanted[j].ID })
var restoredEPs []*e.Endpoint
var restoredEPs []*Endpoint
for _, ep := range eps {
restoredEPs = append(restoredEPs, ep)
}
Expand Down

0 comments on commit 852d91d

Please sign in to comment.