Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CLI command to get memberlist state #4611

Merged
merged 1 commit into from Feb 21, 2023

Conversation

Atish-iaf
Copy link
Contributor

Add an antrea agent command antctl get memberlist to get the state of memberlist cluster of antrea-agent.

root@kind-worker2:/# antctl get memberlist
NODE               IP         STATUS
kind-control-plane 172.18.0.4 Alive 
kind-worker        172.18.0.3 Alive 
kind-worker2       172.18.0.2 Alive 

Fixes #4601

Signed-off-by: Kumar Atish atish.iaf@gmail.com

@codecov
Copy link

codecov bot commented Feb 7, 2023

Codecov Report

Merging #4611 (5659835) into main (9b860d8) will decrease coverage by 0.15%.
The diff coverage is 85.36%.

❗ Current head 5659835 differs from pull request most recent head 6366fd5. Consider uploading reports for the commit 6366fd5 to get more accurate results

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4611      +/-   ##
==========================================
- Coverage   69.78%   69.64%   -0.15%     
==========================================
  Files         401      402       +1     
  Lines       59529    58388    -1141     
==========================================
- Hits        41545    40662     -883     
+ Misses      15166    14928     -238     
+ Partials     2818     2798      -20     
Flag Coverage Δ *Carryforward flag
e2e-tests 38.33% <74.35%> (-0.05%) ⬇️
integration-tests 34.45% <ø> (+0.06%) ⬆️ Carriedforward from 6366fd5
kind-e2e-tests 47.17% <74.35%> (+0.11%) ⬆️ Carriedforward from 6366fd5
unit-tests 59.79% <70.73%> (-0.01%) ⬇️ Carriedforward from 6366fd5

*This pull request uses carry forward flags. Click here to find out more.

Impacted Files Coverage Δ
cmd/antrea-agent/agent.go 0.00% <0.00%> (ø)
pkg/antctl/antctl.go 50.00% <ø> (ø)
pkg/agent/apiserver/handlers/memberlist/handler.go 86.20% <86.20%> (ø)
pkg/agent/apiserver/apiserver.go 71.57% <100.00%> (+0.30%) ⬆️
pkg/agent/querier/querier.go 87.09% <100.00%> (-1.04%) ⬇️
...kg/apiserver/registry/system/supportbundle/rest.go 83.33% <100.00%> (-1.44%) ⬇️
pkg/support/dump.go 62.01% <100.00%> (+0.42%) ⬆️
...g/agent/controller/serviceexternalip/controller.go 69.62% <0.00%> (-11.95%) ⬇️
pkg/agent/controller/egress/egress_controller.go 75.27% <0.00%> (-9.96%) ⬇️
pkg/agent/proxy/topology.go 72.72% <0.00%> (-9.10%) ⬇️
... and 50 more

@Atish-iaf Atish-iaf changed the title Add CLI command to get memberlist state [WIP] Add CLI command to get memberlist state Feb 8, 2023
@Atish-iaf Atish-iaf marked this pull request as ready for review February 9, 2023 07:29
@Atish-iaf Atish-iaf requested a review from tnqn February 9, 2023 07:29
@Atish-iaf Atish-iaf changed the title [WIP] Add CLI command to get memberlist state Add CLI command to get memberlist state Feb 9, 2023
docs/antctl.md Show resolved Hide resolved
docs/support-bundle-guide.md Show resolved Hide resolved
Status string `json:"status,omitempty"`
}

func generateResponse(node v1.Node, aliveNodes sets.String) Response {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
func generateResponse(node v1.Node, aliveNodes sets.String) Response {
func generateResponse(node *v1.Node, aliveNodes sets.String) Response {

to avoid copy

func HandleFunc(aq querier.AgentQuerier) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var memberlist []Response
allNodes, err := aq.GetK8sClient().CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
Copy link
Member

Choose a reason for hiding this comment

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

The agent already caches all Nodes in memory, it could use NodeInformer's Lister to get all Nodes, intead of making an API call, which is not cheap in scale cluster.

return func(w http.ResponseWriter, r *http.Request) {
var memberlist []Response
allNodes, err := aq.GetK8sClient().CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
if err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

After switching to NodeInformer, it would never fail, so error could be ignored.

@@ -55,6 +58,7 @@ type agentQuerier struct {
networkPolicyInfoQuerier querier.AgentNetworkPolicyInfoQuerier
apiPort int
nplRange string
memberlistCluster *memberlist.Cluster
Copy link
Member

Choose a reason for hiding this comment

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

Use Interface instead of concrete type

aliases: []string{"ml"},
short: "Print state of memberlist cluster",
long: "Print state of memberlist cluster of Antrea agent",
example: ` Get a memberlist
Copy link
Member

Choose a reason for hiding this comment

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

Since there is only one usage, this example looks verbose, could be deleted

Copy link
Contributor Author

@Atish-iaf Atish-iaf Feb 9, 2023

Choose a reason for hiding this comment

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

deleted, thanks.

docs/support-bundle-guide.md Show resolved Hide resolved
Comment on lines 36 to 56
node1 = v1.Node{
ObjectMeta: metav1.ObjectMeta{Name: "node1"},
Status: v1.NodeStatus{
Addresses: []v1.NodeAddress{
{
Address: "172.16.0.11",
},
},
},
}

expectedContent = []Response{
{
NodeName: "node1",
IP: "172.16.0.11",
Status: "Alive",
},
}
Copy link
Member

Choose a reason for hiding this comment

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

  1. Move the expected response to the test to be self-contained. Expected response is not likely to be reused.
  2. It should include a dead node to cover the negaive case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

@@ -42,6 +45,8 @@ type AgentQuerier interface {
GetOVSCtlClient() ovsctl.OVSCtlClient
GetProxier() proxy.Proxier
GetNetworkPolicyInfoQuerier() querier.AgentNetworkPolicyInfoQuerier
GetAliveNodes() sets.String
Copy link
Member

Choose a reason for hiding this comment

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

I feel the AgentQuerier is perhaps a bad interface which mixes too many things which breaks a few OOP rules. I understand the change is following existing code, however, it should use the same style to return a ClusterInterface and let the client to call its GetAliveNodes interface to be consistent, instead of playing a proxy here.

@Atish-iaf Atish-iaf force-pushed the antctl-get-memberlist branch 2 times, most recently from 98474c0 to 187eff5 Compare February 14, 2023 05:33
@Atish-iaf Atish-iaf requested a review from tnqn February 14, 2023 06:00
@@ -41,7 +41,7 @@ MOCKGEN_TARGETS=(
"pkg/agent/cniserver/ipam IPAMDriver testing"
"pkg/agent/flowexporter/connections ConnTrackDumper,NetFilterConnTrack testing"
"pkg/agent/interfacestore InterfaceStore testing"
"pkg/agent/memberlist Memberlist testing"
"pkg/agent/memberlist Interface,Memberlist . mock_memberlist.go"
Copy link
Member

Choose a reason for hiding this comment

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

I don't get why this change is made. Is it related to my comment here #4611 (comment)? If yes, I think it's misunderstood. I meant querier interface should provide a method to return memberlist.Interface, instead of providing a method GetAliveNodes and playing as a proxy.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tnqn
This change is because :-

  1. I needed to mock Interface of memberlist package which has AliveNodes method in order to write unit test (pkg/agent/apiserver/handlers/memberlist/handler_test.go) [Line 75 and 78].
  2. Now, after mocking Interface of memberlist package in testing sub package i was getting cyclic import issue, so to avoid that I created mock in the memberlist package itself.
  3. Now, mock file was created as mock_memberlist_test.go, I changed that to mock_memberlist.go inorder to make methods exportable as I needed it in unit test (handler_test.go).

Copy link
Member

Choose a reason for hiding this comment

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

Could you describe the cyclic import? I don't see it from the imports even if the file is in testing package.

Copy link
Contributor Author

@Atish-iaf Atish-iaf Feb 15, 2023

Choose a reason for hiding this comment

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

Hi @tnqn
If we create mock for interfaces Memberlist and Interface in a file inside testing subpackage, it would import "antrea.io/antrea/pkg/agent/memberlist" as it is required for mock of method AddClusterEventHandler of interafce Interface.
Now, we get cyclic import error in cluster.go and cluster_test.go as cluster_test.go imports this testing subpackage.

Copy link
Member

Choose a reason for hiding this comment

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

OK, now I see there is a MockMemberlist in the testing package. Normally the testing has a mock implementation of the interface its parent package provides, and it's intended to be used by the interface's consumers in their tests, and the parent package wouldn't consume its own testing (and the testing package will likely consume the parent package because of the type import).

However, just moving the two mock structs to the parent package would cause other "problems":
If the mock structs are put in a file with "_test.go" suffix, they won't be exported and we can't use MockInterface.
If the mock structs are put in a file without "_test.go" suffix, they will be compiled and linked into the product code unnecessarily.

I would suggest to follow the mode that keeps the mock implementation of the target interface in testing package, and keeps the mock implementation of the dependent interface in "mock_memberlist_test.go" in the parent package as it's not intended to be consumed out of the package.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tnqn done, thanks for the suggestion.

Comment on lines 61 to 71
clientset := fake.NewSimpleClientset()
informerFactory := informers.NewSharedInformerFactory(clientset, 0)
nodeInformer := informerFactory.Core().V1().Nodes()

stopCh := make(chan struct{})
defer close(stopCh)

informerFactory.Start(stopCh)
informerFactory.WaitForCacheSync(stopCh)
informerFactory.Core().V1().Nodes().Informer().GetIndexer().Add(&node1)
informerFactory.Core().V1().Nodes().Informer().GetIndexer().Add(&node2)
Copy link
Member

Choose a reason for hiding this comment

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

It looks neater to pass the two objects when creating the clientset. It needs an "informer" or "lister" to be created first by calling nodeInformer.Informer() or nodeInformer.Lister(). But I feel AgentQuerier just needs NodeLister so maybe change the passed type to resolve the it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done, thanks!

Comment on lines 103 to 106
sort.Slice(received, func(i, j int) bool {
return received[i].NodeName < received[j].NodeName
})
assert.Equal(t, expectedResponse, received)
Copy link
Member

Choose a reason for hiding this comment

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

assert.ElementsMatch

Add antrea agent command `antctl get memberlist`
to get state of memberlist cluster of antrea agent.

Fixes antrea-io#4601

Signed-off-by: Kumar Atish <atish.iaf@gmail.com>
Copy link
Member

@tnqn tnqn left a comment

Choose a reason for hiding this comment

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

LGTM, thanks

@tnqn
Copy link
Member

tnqn commented Feb 21, 2023

/test-all

@tnqn tnqn added area/component/antctl Issues or PRs releated to the command line interface component action/release-note Indicates a PR that should be included in release notes. labels Feb 21, 2023
@tnqn
Copy link
Member

tnqn commented Feb 21, 2023

/skip-e2e which failed on known flaky test

@tnqn tnqn merged commit 8eb5c8d into antrea-io:main Feb 21, 2023

### Showing memberlist state

`antctl` agent command `get memberlist` (or `get ml`) print the state of memberlist cluster of Antrea Agent.
Copy link
Contributor

Choose a reason for hiding this comment

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

print -> prints

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
action/release-note Indicates a PR that should be included in release notes. area/component/antctl Issues or PRs releated to the command line interface component
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CLI command for getting memberlist state
3 participants