Skip to content

Conversation

@DancingLinks
Copy link
Contributor

What this PR does / why we need it:

Which issue this PR fixes (optional, in fixes #<issue number>(, fixes #<issue_number>, ...) format, will close that issue when PR gets merged): fixes #

Special notes for your reviewer:

Release note:

@DancingLinks
Copy link
Contributor Author

@tamilmani1989, @matmerr, @jaer-tsun. Hi all, I'm an SWE Intern to ASK China team. My leader and mentor want me to be familiar with Azure CNI, and add some unit tests for it. So I mentioned this PR after learning the code of Azure CNI.

This PR mainly adds some unit tests of IPAM to ensure that each function can get the expected results. To make the test code look clearer, I used ginkgo as the unit test framework.

I hope you can spare time to review my PR. If there is any problem, I will correct it in time. You can also connect me on Teams, my alias is t-yuqian :)

At present, I am adding unit tests for the network package.

@jaer-tsun
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

ipam/null.go Outdated

// Set the local address space as active.
s.sink.setAddressSpace(local)
if err := s.sink.setAddressSpace(local); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return s.sink.setAddressSpace(local)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get

"github.com/Azure/azure-container-networking/platform"
cniSkel "github.com/containernetworking/cni/pkg/skel"
cniTypesCurr "github.com/containernetworking/cni/pkg/types/current"
. "github.com/onsi/ginkgo"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't use submodules in this repo so please vendor via go-dep

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm now using go-dep instead, adding github.com/onsi/ginkgo, github.com/onsi/gomega and gopkg.in/fsnotify.v1

testAgent, err := common.NewListener(u)
func parseResult(stdinData []byte) (*cniTypesCurr.Result, error) {
result := &cniTypesCurr.Result{}
err := json.Unmarshal(stdinData, result)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for single returns, current style is to keep it on the same line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get, thanks!

_ = Describe("Test IPAM", func() {

var (
config common.PluginConfig
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like linter didn't work here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will move config to the Context where it works


func parseResult(stdinData []byte) (*cniTypesCurr.Result, error) {
result := &cniTypesCurr.Result{}
err := json.Unmarshal(stdinData, result)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

current style is to merge with if statement for single returns
e.g.

if err := json.Marshal...; err != nil {
...
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, thanks!

Scope: scope,
Pools: make(map[string]*addressPool),
}, nil
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for else block

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll remove it

options[common.OptEnvironment] = common.OptEnvironmentFileIpam
fileIpam, _ := newFileIpamSource(options)
type addressManagerMock struct {
newAddressSpaceSucc bool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type out Succ

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok!

func (sink *addressManagerMock) setAddressSpace(*addressSpace) error {
if sink.setAddressSpaceSucc {
return nil
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for else block

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll remove it

Copy link
Member

@tamilmani1989 tamilmani1989 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. Reviewed half. will review remaining later. One concern is that description of each test case. its little confusing if its pool or address

}
func getStdinData(cniversion, ifname, subnet, ipAddress string) []byte {
stdinData := fmt.Sprintf(
`{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space damage

fmt.Printf("Failed to create IPAM plugin, err:%v.\n", err)
return
}
func getIfName() (string, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this ? What this function expected to return? I think this is for pod interface name right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I copy this code from network.go, for getting the interface name of the test environment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about just using a fake interface name, say eth0, for simplicity? We'll not setup and configure an interface, anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In cni/network/network.go 145, it will detect the in used interface name. For network.go get the same interface name as the test code, I added this function...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the problem is if there are multiple interfaces, if it returns lo adapter or docker0 bridge as 1st interface, then this will break. for simplicity you can keep it as eth0

Copy link
Member

@mainred mainred Apr 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank @DancingLinks for your clarification.

the problem is if there are multiple interfaces, if it returns lo adapter or docker0 bridge as 1st interface, then this will break. for simplicity you can keep it as eth0

After re-reading the code, @DancingLinks and I found that we do not have an interface check, so both lo and docker0 will still work. But in practise, lo and docker0 will not be picked for mac address mismatch.

Also, I found that interface name is not specified for the Kubernetes case[1]. How about we first cover the path without an interface name when invoking the IPAM plugin.
If we have to select a real interface name, how about removing lo and docker0 from the interface list and pick one randomly, in case we may have interface names other than eth0, in different OS releases? This seems to be more real.

[1]https://github.com/kubernetes/kubernetes/blob/581d3e26c97ade852b54bc7f102f1a4d16b74437/pkg/kubelet/dockershim/network/cni/cni.go#L353

var result *cniTypesCurr.Result

Context("When ADD with nothing (request pool)", func() {
It("Request pool and ADD successfully", func() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this for request pool or request address or for both?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both. I found that this case may happen when request pool.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then update description saying this is test for ipam add call

Gopkg.toml Outdated
# go-tests = true
# unused-packages = true

[[override]]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this package for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this signed off by lca?

@jaer-tsun jaer-tsun requested a review from tamilmani1989 March 11, 2020 00:25
@jaer-tsun
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Contributor

@jaer-tsun jaer-tsun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, waiting on @tamilmani1989 final review

Copy link
Member

@mainred mainred left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your commits. Please remove Submodule.

})
})
})
) No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may need a newline here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll add a newline here :) forgot

fmt.Printf("Failed to create IPAM plugin, err:%v.\n", err)
return
}
func getIfName() (string, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about just using a fake interface name, say eth0, for simplicity? We'll not setup and configure an interface, anyway.


Context("When address and subnet is given", func() {
It("ADD address successfully with the given address", func() {
arg.StdinData = getStdinData("0.4.0", ifName, "10.0.0.0/16", "10.0.0.6")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using another CIDR instead of the default one 10.0.0.0/16? So that we can test the returned IP address is not from the default CIDR.

"testing"

"github.com/Azure/azure-container-networking/common"
"time"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following package groups sequence convention is very popular:

  1. standard library
  2. third-party packages
  3. local packages
    Could you please adjust your code to comply with this?

CC @tamilmani1989

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my only concern with 3rd party is we have to get approval from lca before using that..did we get required approval?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for pointing this out. I am not sure about the newly imported packages in this PR.
I saw from our Golang files that we are using different package group conventions, so I here just want to share my idea to follow one convention.

err error
)

BeforeSuite(func() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please correct me if I am wrong, BeforeSuite and AfterSuite is suitable to be outside of the Describe clause as suite-scoped resources.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll move them outside of the Describe, thx!

Copy link
Member

@tamilmani1989 tamilmani1989 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR. Really appreciate the effort. Left some comments

Gopkg.toml Outdated
# go-tests = true
# unused-packages = true

[[override]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this signed off by lca?

cniSkel "github.com/containernetworking/cni/pkg/skel"
cniTypesCurr "github.com/containernetworking/cni/pkg/types/current"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are these 3rd party packages signed by microsoft legal (lca)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this, but we have these two packages used in repos like aks-engine already.
https://github.com/search?q=org%3AAzure+github.com%2Fonsi%2Fginkgo&type=Code

fmt.Printf("Failed to create IPAM plugin, err:%v.\n", err)
return
}
func getIfName() (string, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the problem is if there are multiple interfaces, if it returns lo adapter or docker0 bridge as 1st interface, then this will break. for simplicity you can keep it as eth0

var result *cniTypesCurr.Result

Context("When ADD with nothing (request pool)", func() {
It("Request pool and ADD successfully", func() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then update description saying this is test for ipam add call

})
})

Context("When time interval is less", func() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couldnot understand what this test for..what we are testing here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither can I. Let's remove this test unless you can make it more descriptive and please also remember test will also be maintained as part of our code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will change the description as "refresh interval is too short". It may be more clearly now.


Context("When newAddressSpace err", func() {
It("Exit with error when refresh", func() {
sink := &addressManagerMock{false, true}
Copy link
Member

@tamilmani1989 tamilmani1989 Mar 31, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what this mock does..can you add a comment ..is addressmanagermock defined somewhere

"testing"

"github.com/Azure/azure-container-networking/common"
"time"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my only concern with 3rd party is we have to get approval from lca before using that..did we get required approval?

RefCount: 1,
Addresses: make(map[string]*addressRecord),
}
ap.Addresses["ar-test"] = &addressRecord{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we also add some addr and check if addrbyid returns that address...thats the main purpose of addrsbyid

t.Errorf("ReleasePool failed, err:%v", err)
}
}
var (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was unit test for requestpool, requestaddr, releaseddr, releasepool moved somewhere else?

@tamilmani1989 tamilmani1989 self-requested a review March 31, 2020 08:47
mainred
mainred previously approved these changes Mar 31, 2020
Copy link
Member

@mainred mainred left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM from my part, but please let @tamilmani1989 make the decision.

@tamilmani1989
Copy link
Member

@DancingLinks Can you rebase and push it again?

@mainred
Copy link
Member

mainred commented Apr 7, 2020

@DancingLinks, besides rebasing your code, could you please also squash your commits and reword your commit messages to explain your changes neatly before we merge this PR?

@DancingLinks
Copy link
Contributor Author

@tamilmani1989 rebased finished :)

@DancingLinks
Copy link
Contributor Author

@mainred Thanks a lot for your suggestion! I've now merged them in a single commit.

@tamilmani1989
Copy link
Member

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

2. Using ginkgo instead of the origin go test
@tamilmani1989
Copy link
Member

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Member

@tamilmani1989 tamilmani1989 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@tamilmani1989 tamilmani1989 merged commit 512ffed into Azure:master Apr 9, 2020
@DancingLinks DancingLinks deleted the ipamtest branch April 9, 2020 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants