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

Implement antctl get pod-interface [podName] #334

Merged
merged 1 commit into from
Mar 19, 2020

Conversation

lzhecheng
Copy link
Contributor

@lzhecheng lzhecheng commented Jan 20, 2020

Issue #275

Implemented antctl subcommand: pod-interface

  • This command is under get group to get pod interface information.
    Users can filter the result with "podName" as an arg or "namespace"
    as an flag. The default namespace is "default".
  • Removed duplicated flag in commandDefinition.
  • Support bool flag

The output should be like this:

{
  "name": "patch-demo-c8796b6dd-5k6qn",
  "InterfaceName": "patch-de-17bf25",
  "IP": "192.168.2.7",
  "MAC": "36:44:77:45:ee:55",
  "PortUUID": "e2bc4318-5cda-4be9-ab61-8ff748db7320",
  "OFPort": 8,
  "ContainerID": "58e4aba280fe1696a647aa0f928071a3bfb25a9da21937dcdc05200fce39ca20",
  "PodNamespace": "default"
}

@antrea-bot
Copy link
Collaborator

Thanks for your PR.
Unit tests and code linters are run automatically every time the PR is updated.
E2e, conformance and network policy tests can only be triggered by a member of the vmware-tanzu organization. Regular contributors to the project should join the org.

The following commands are available:

  • /test-e2e: to trigger e2e tests.
  • /skip-e2e: to skip e2e tests.
  • /test-conformance: to trigger conformance tests.
  • /skip-conformance: to skip conformance tests.
  • /test-networkpolicy: to trigger networkpolicy tests.
  • /skip-networkpolicy: to skip networkpolicy tests.
  • /test-all: to trigger all tests.
  • /skip-all: to skip all tests.

These commands can only be run by members of the vmware-tanzu organization.

@lzhecheng lzhecheng changed the title WIP: Implement antctl get pod [podName] Implement antctl get pod [podName] Jan 21, 2020
@lzhecheng
Copy link
Contributor Author

/test-all

@lzhecheng
Copy link
Contributor Author

/test-networkpolicy

Copy link
Contributor

@antoninbas antoninbas left a comment

Choose a reason for hiding this comment

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

I may be missing something, but it seems that the command should use the Namespace as well as the Pod name.

IMO, if I have 2 Pods with the same name in 2 different namespaces, I should be able to select a single one. It doesn't seem like it is the case right now. It seems that you stop at the first Pod for which the name matches?

Also, as I commented on the agent-info PR, will we be able to run this command from out-of-cluster (from out of the agent Pod)? That would be very useful.

@@ -72,6 +72,7 @@ type InterfaceStore interface {
GetContainerInterface(podName string, podNamespace string) (*InterfaceConfig, bool)
GetNodeTunnelInterface(nodeName string) (*InterfaceConfig, bool)
GetContainerInterfaceNum() int
GetContainerInterfaces() []*InterfaceConfig
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe others will disagree but I would suggest having a more generic GetInterfacesByType(interfaceType InterfaceType) interface method - like we have GetInterfaceKeysByType below. Maybe it will help keep the number of methods for this interface "reasonable".

Copy link
Contributor Author

@lzhecheng lzhecheng Jan 22, 2020

Choose a reason for hiding this comment

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

Do you mean make the command like antctl get pod podName -n nsName ? Do you use namespace to filter for CRD @mengdie-song ?
Then if user doesn't specify the namespace name, let's show all pods with different namespaces ?

Yes, we can run this command remotely with future implementation.

Copy link
Contributor

Choose a reason for hiding this comment

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

@lzhecheng For CRD, currently we only have the field LocalPodNum to show the number of Pod. I did not distinguish them by namespaces. I can enhance this part if we want more information for local pods in CRD. But if the number of Pods is too large, I am afraid the CRD is not friendly way to show.

However, CLI can show more information than CRD if we want. Since this patch has already added a separate function GetContainerInterfaces to get details, we can get Pod namespace from InterfaceConfig if we would like to show it via CLI.

@@ -76,6 +78,16 @@ var CommandList = &commandList{
CommandGroup: flat,
AddonTransform: versionTransform,
},
{
Use: "pod",
Short: "Print pod's basic information",
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest using "Pod" and not "pod" for user-facing messages, for the sake of consistency.

Copy link
Contributor

Choose a reason for hiding this comment

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

+1

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reasonable. Updated.

@@ -0,0 +1,74 @@
// Copyright 2020 Antrea Authors
Copy link
Contributor

Choose a reason for hiding this comment

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

should the file be named "get_pod.go" instead since this is the "pod" subcommand in the "get" command group? Would it be possible to have a "pod" subcommand in another command group?

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, it is possible. Updated.

{
Use: "pod",
Short: "Print pod's basic information",
Long: "Print pod's basic information of interface config.",
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: "Print information about the network interface(s) created by the Antrea agent for the specified Pod".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

Copy link
Contributor

@jianjuns jianjuns left a comment

Choose a reason for hiding this comment

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

A general question for this cmd - do we plan to add more information about the Pod later? If it is just about Pod interface info, maybe name it get pod-interface?

@@ -113,6 +115,11 @@ func (monitor *agentMonitor) GetLocalPodNum() int32 {
return int32(monitor.interfaceStore.GetContainerInterfaceNum())
}

// GetContainerInterfaces gets the information of the pod with podName.
func (monitor *agentMonitor) GetContainerInterfaces() []*interfacestore.InterfaceConfig {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would stop adding more CLI code to Agent/ControllerMonitor which is originally for MonitorCRD.
But we can decide this together with other changes I suggested like extracting API server code out of CLI.

@@ -76,6 +78,16 @@ var CommandList = &commandList{
CommandGroup: flat,
AddonTransform: versionTransform,
},
{
Use: "pod",
Short: "Print pod's basic information",
Copy link
Contributor

Choose a reason for hiding this comment

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

+1

Copy link
Contributor

@jianjuns jianjuns left a comment

Choose a reason for hiding this comment

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

Could you provide an example output of the command? I have three general questions:

  1. Should we add the namespace argument (like --namespace/-N just like kubectl).
  2. Should we support getting all Pods (Pod name is not specified).
  3. If the command is for Pod interface configuration only? If so should we name it get pod-interface; if not should we define a separate struct like PodInfo for future extension, instead of using InterfaceConfig directly.
    @tnqn

@lzhecheng lzhecheng changed the title Implement antctl get pod [podName] WIP: Implement antctl get pod [podName] Feb 5, 2020
@lzhecheng
Copy link
Contributor Author

lzhecheng commented Feb 5, 2020

Could you provide an example output of the command? I have three general questions:

  1. Should we add the namespace argument (like --namespace/-N just like kubectl).
  2. Should we support getting all Pods (Pod name is not specified).
  3. If the command is for Pod interface configuration only? If so should we name it get pod-interface; if not should we define a separate struct like PodInfo for future extension, instead of using InterfaceConfig directly.
    @tnqn

I just put an example in the description of this PR.

  1. Yes, this is under development.
  2. Yes, this has been implemented.
  3. I agree we can change the command name to "pod-interface".

@lzhecheng lzhecheng force-pushed the get-pod branch 2 times, most recently from afc56b7 to 53fc250 Compare February 6, 2020 10:54
@lzhecheng
Copy link
Contributor Author

/test-networkpolicy

@lzhecheng lzhecheng force-pushed the get-pod branch 3 times, most recently from e8f65f0 to 251059a Compare March 9, 2020 09:45
@@ -52,6 +53,7 @@ func (s *agentAPIServer) Run(stopCh <-chan struct{}) error {

func installHandlers(aq monitor.AgentQuerier, npq monitor.AgentNetworkPolicyInfoQuerier, s *genericapiserver.GenericAPIServer) {
s.Handler.NonGoRestfulMux.HandleFunc("/agentinfo", agentinfo.HandleFunc(aq))
s.Handler.NonGoRestfulMux.HandleFunc("/getpodinterface", getpodinterface.HandleFunc(aq))
Copy link
Member

Choose a reason for hiding this comment

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

Restful api doesn't have verb in url path, which should be expressed by http method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

@@ -150,19 +150,19 @@ func main() {
failOnError(err)

testList := []*TestCase{
&TestCase{"DefaultDeny", testDefaultDeny()},
Copy link
Member

Choose a reason for hiding this comment

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

I understand they are redundant but better to not touch unrelated code so that reviewers can focus on your change and there won't be surprise when seeing git history that some lines are changed in an unrelated PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed since this is fixed in other PR.

m := make(map[string][]*interfacestore.InterfaceConfig)
for _, v := range aq.GetInterfacesByType(interfacestore.ContainerInterface) {
podName := (*v.ContainerInterfaceConfig).PodName
vPodNS := (*v.ContainerInterfaceConfig).PodNamespace
Copy link
Member

Choose a reason for hiding this comment

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

why is there a "v" prefix for namespace only?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There used to be other var named podNS so I added "v" to avoid conflict. Now it is ok to name it "podNS".

if (!doFilter || key[0] == podName) && ns[0] == vPodNS {
m[podName] = append(m[podName], v)
}
fmt.Println("podName:", podName, "vPodNS:", vPodNS)
Copy link
Member

Choose a reason for hiding this comment

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

Why using Println in server 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.

It is not final code and only for debugging. Removed.

func HandleFunc(aq monitor.AgentQuerier) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if aq == nil {
w.WriteHeader(http.StatusNotImplemented)
Copy link
Member

Choose a reason for hiding this comment

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

This is a closure so aq has been decided before serving requests. If aq could possibly be nil, I would prefer we return error at the earliest place so that we don't need to check aq in every subroutine of the call stack.
Actually I checked agent.go has made sure aq cannot be nil so this check is not necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for reminding. Code is not updated according to refactored framework.

for _, v := range aq.GetInterfacesByType(interfacestore.ContainerInterface) {
podName := (*v.ContainerInterfaceConfig).PodName
vPodNS := (*v.ContainerInterfaceConfig).PodNamespace
if (!doFilter || key[0] == podName) && ns[0] == vPodNS {
Copy link
Member

Choose a reason for hiding this comment

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

Is namespace a mandatory field? Is it safe to assume len(ns) > 0?

Copy link
Contributor Author

@lzhecheng lzhecheng Mar 10, 2020

Choose a reason for hiding this comment

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

namespace has a default value and if no value after "-n", it will return Error: flag needs an argument: 'n' in -n.

if err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
}
Copy link
Member

Choose a reason for hiding this comment

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

This can be simpler:

if doFilter and len(m) == 0 {
	w.WriteHeader(http.StatusNotFound)
} else {
	var pods []GetPodInterfaceResponse
	for k, v := range m {
		pods = append(pods, GetPodInterfaceResponse{k, v})
	}
	err := json.NewEncoder(w).Encode(pods)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
	}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Refactored.

return
}

m := make(map[string][]*interfacestore.InterfaceConfig)
Copy link
Member

Choose a reason for hiding this comment

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

Why using map and having the podname as the key? Is there any reason pods having same name but in different namespaces needs to be grouped together?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Refactored.

@tnqn
Copy link
Member

tnqn commented Mar 9, 2020

Could you provide an example output of the command? I have three general questions:

  1. Should we add the namespace argument (like --namespace/-N just like kubectl).
  2. Should we support getting all Pods (Pod name is not specified).
  3. If the command is for Pod interface configuration only? If so should we name it get pod-interface; if not should we define a separate struct like PodInfo for future extension, instead of using InterfaceConfig directly.
    @tnqn

@jianjuns, sorry for missing the notification. All sounds good to me.

@lzhecheng lzhecheng force-pushed the get-pod branch 4 times, most recently from dfaefd5 to 96a3cb1 Compare March 10, 2020 07:30
@lzhecheng
Copy link
Contributor Author

/test-e2e

@lzhecheng
Copy link
Contributor Author

I followed @jianjuns 's suggestion and updated the code.

@lzhecheng
Copy link
Contributor Author

/test-all

// Response describes the internal response struct of pod-interface command.
type Response struct {
PodName string `json:"name,omitempty" yaml:"name,omitempty" antctl:"name,The name of the pod"`
PodInterfaces []PodInterface `json:",inline" yaml:",inline"`
Copy link
Member

Choose a reason for hiding this comment

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

Again, why multiple interfaces with same Pod name are grouped together? They are logically unrelated, I think the previous flatten struct works.

podName := (*v.ContainerInterfaceConfig).PodName
podNS := (*v.ContainerInterfaceConfig).PodNamespace
if (len(name) == 0 || name == podName) && (len(ns) == 0 || ns == podNS) {
m[podName] = append(m[podName], generatePodInterface(podName, v))
Copy link
Member

Choose a reason for hiding this comment

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

ditto, is there any problem using a slice to keep result?

}
}
} else {
var pods []Response
Copy link
Member

Choose a reason for hiding this comment

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

The 3 branches can be simplified as:

if len(name) > 0 && len(m) == 0 {
    w.WriteHeader(http.StatusNotFound)
    return
}
var pods []Response
...

@lzhecheng lzhecheng force-pushed the get-pod branch 2 times, most recently from ab76612 to 8280564 Compare March 17, 2020 11:22
@lzhecheng lzhecheng requested a review from tnqn March 17, 2020 11:22
@lzhecheng
Copy link
Contributor Author

Code updated to avoid grouping pods with same name but in different namespaces together. isSingle field in nonResourceEndpoint is turned into outputType, an enum including default, single and multiple.

@lzhecheng
Copy link
Contributor Author

/test-all

@lzhecheng
Copy link
Contributor Author

/test-e2e
/test-conformance

if len(name) > 0 && len(pods) == 0 {
w.WriteHeader(http.StatusNotFound)
} else {
err := json.NewEncoder(w).Encode(pods)
Copy link
Member

Choose a reason for hiding this comment

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

nit: keep the normal code path at a minimal indentation, and indent the error handling, dealing with it first https://github.com/golang/go/wiki/CodeReviewComments#indent-error-flow

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated

type OutputType uint

const (
dflt OutputType = iota
Copy link
Member

Choose a reason for hiding this comment

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

"default" is shorter than "multiple", why use short for it alone? and this short doesn't seem common.

Copy link
Contributor Author

@lzhecheng lzhecheng Mar 18, 2020

Choose a reason for hiding this comment

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

I think "default" is reserved? Let's change it to "defaultType"

@@ -62,7 +69,7 @@ var groupCommands = map[commandGroup]*cobra.Command{
}

type endpointResponder interface {
single() bool
output() OutputType
Copy link
Member

Choose a reason for hiding this comment

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

output sounds like an action, maybe "outputType" to avoid confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IMO, "output" sounds like a noun which is shorter like the original "single". Also, if changed, we will have outputType() as a function and a outputType as a field in nonResourceEndpoint, which is confusing I think.

Copy link
Member

Choose a reason for hiding this comment

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

Of course it can sound like a noun but it means the output of the responder? I don't know if it's only me who will be confused by the function name. AFAIK, Output is widely used by exec, command, http request to get the output and the noun output is used to take the return value.
Besides, if output is really clear for the mean of outputType, why the type is named OutputType while the method is named output?
Defining a method to get the field with same name is quite common regardless of languages, it's even encouraged to do it in Golang (to save the prefix Get), I don't think it's confusing.

If you have a field called owner (lower case, unexported), the getter method should be called Owner (upper case, exported), not GetOwner.

https://golang.org/doc/effective_go.html#Getters

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for sharing the doc. But outputType() cannot work, it returns type nonResourceEndpoint has both field and method named outputType. I choose OutputType() instead.

expect string
}{
"SingleObject": {
"outputObject": {
Copy link
Member

Choose a reason for hiding this comment

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

This case is still testing single object, why change the case name?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated. Thanks for reminding me cuz I changed it by mistake.

@@ -108,13 +108,13 @@ func TestCommandDefinitionGenerateExample(t *testing.T) {
for k, tc := range map[string]struct {
use string
cmdChain string
singleObject bool
outputObject OutputType
Copy link
Member

Choose a reason for hiding this comment

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

why not use outputType as variable name?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

// StringFlag represents a string flag
StringFlag FlagType = iota
// BoolFlag represents a boolean flag
BoolFlag
Copy link
Member

Choose a reason for hiding this comment

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

Do we still need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed, BoolFlag is not applied by any commands now. However, I suggest keeping it since these newly-added types not just add support for "bool" flag but also it refactors the code to adapt more kinds of flags in the future. Unless there will only be string flag, I think it is worthwhile to keep these changes.

Copy link
Member

Choose a reason for hiding this comment

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

Then we should add this the first time it is used, not assuming it can be used one day unpredictably. Some people are even dedicated to clean up functions, structs that are no longer used no matter how useful they used to be. We shouldn't do the opposite thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed.

@lzhecheng lzhecheng force-pushed the get-pod branch 2 times, most recently from d2aa81a to 92342ae Compare March 18, 2020 10:58
argMap[f.name] = vs
continue
}
// flag is bool
Copy link
Member

Choose a reason for hiding this comment

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

are they still needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed.

const (
defaultType OutputType = iota
single
multiple
Copy link
Member

Choose a reason for hiding this comment

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

I think it's worth to add comments for this values, it took me a while to understand, maybe others will have question too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comments added.

Copy link
Contributor

@weiqiangt weiqiangt left a comment

Choose a reason for hiding this comment

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

Overall, LGTM, some nits left.

@@ -118,6 +120,11 @@ func (monitor *agentMonitor) GetLocalPodNum() int32 {
return int32(monitor.interfaceStore.GetContainerInterfaceNum())
}

// GetInterfacesByType gets the interface information by type.
func (monitor *agentMonitor) GetInterfacesByType(interfaceType interfacestore.InterfaceType) []*interfacestore.InterfaceConfig {
Copy link
Contributor

Choose a reason for hiding this comment

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

@jianjuns Do you think we should access interfacestore in the handler directly?

defaultType OutputType = iota
// single represents the output type is single item.
single
// multiple represents the output type is list.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit, maybe add the modifier always?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

@@ -473,7 +496,7 @@ func (cd *commandDefinition) newCommandRunE(c *client) func(*cobra.Command, []st
if err != nil {
return err
}
return cd.output(resp, os.Stdout, formatterType(outputFormat), cd.getEndpoint().single() || argGet)
return cd.output(resp, os.Stdout, formatterType(outputFormat), cd.getEndpoint().OutputType() != multiple && (cd.getEndpoint().OutputType() == single || argGet))
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: it would be better to have a variable for cd.getEndpoint().OutputType() != multiple && (cd.getEndpoint().OutputType() == single || argGet).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated

isSingle bool
path string
params []flagInfo
outputType OutputType
Copy link
Contributor

Choose a reason for hiding this comment

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

Have a question here: for registered APIGroup exposed via API Server, could we have the "single" case, but is the API path exposes a single object, but not a type of resources?
I am asking because I am adding the controller-info cmd which should be exposed via aggregated API, and wondering it should be declared as a resourceEndpoint or nonResourceEndpoint in antctl.go. The former does not have the "single" type now,
@weiqiangt @tnqn

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the controller-info is a similar case of version.
If you specified a resourceName, the antctl would always assume the response is single. The antctl does not know what the content is but just dispatch the response to the transform function according to definition.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure. My question is could resourceEndpoint also have the "single" type case, or it should be always "multiple"?

Copy link
Contributor

Choose a reason for hiding this comment

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

For now, if a resourceEndpoint specified resourceName then it is single inexplicitly, otherwise, the antctl will only assume the response is single when running command with arg.
I don't think @lzhecheng implemented multiple for resourceEndpoint, but developers can make the both single transform func and list transform func expect same type to hack a multiple behavior.

* This command is under get group to get pod interface information.
Users can filter the result with "podName" as an arg or "namespace"
as an flag. The default namespace is "default".
* Remove duplicated flag in commandDefinition.
* Turn isSingle field in nonResourceEndpoint to outputType which is an enum,
including default, single and multiple

Co-Authored-By: Antonin Bas <[email protected]>
@jianjuns
Copy link
Contributor

LGTM

@lzhecheng
Copy link
Contributor Author

/test-all

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

@lzhecheng lzhecheng merged commit 3d5e14c into antrea-io:master Mar 19, 2020
@lzhecheng lzhecheng deleted the get-pod branch March 19, 2020 07:21
ZhangYW18 pushed a commit to ZhangYW18/antrea that referenced this pull request Mar 23, 2020
* This command is under get group to get pod interface information.
Users can filter the result with "podName" as an arg or "namespace"
as an flag. The default namespace is "default".
* Remove duplicated flag in commandDefinition.
* Turn isSingle field in nonResourceEndpoint to outputType which is an enum,
including default, single and multiple

Co-Authored-By: Antonin Bas <[email protected]>
ZhangYW18 added a commit to ZhangYW18/antrea that referenced this pull request Mar 23, 2020
ZhangYW18 added a commit to ZhangYW18/antrea that referenced this pull request Mar 23, 2020
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.

8 participants