From 00dcae1755c9bbe05d560032b84b63f60ed34f2c Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Thu, 13 Aug 2020 21:00:28 -0700 Subject: [PATCH 01/10] feat: add cns debug api and cli --- cns/NetworkContainerContract.go | 36 +++++++++---- cns/cnsclient/cli.go | 92 +++++++++++++++++++++++++++++++++ cns/cnsclient/cnsclient.go | 56 +++++++++++++++++++- cns/cnsclient/cnsclient_test.go | 2 +- cns/restserver/internalapi.go | 2 +- cns/restserver/ipam.go | 59 +++++++++++++++++++-- cns/restserver/ipam_test.go | 20 +++---- cns/restserver/restserver.go | 1 + cns/service/main.go | 22 ++++++++ common/config.go | 8 +++ 10 files changed, 271 insertions(+), 27 deletions(-) create mode 100644 cns/cnsclient/cli.go diff --git a/cns/NetworkContainerContract.go b/cns/NetworkContainerContract.go index 4f0940e9a6..7b1e8c6e71 100644 --- a/cns/NetworkContainerContract.go +++ b/cns/NetworkContainerContract.go @@ -22,6 +22,7 @@ const ( DetachContainerFromNetwork = "/network/detachcontainerfromnetwork" RequestIPConfig = "/network/requestipconfig" ReleaseIPConfig = "/network/releaseipconfig" + GetIPAddresses = "/network/getipconfigs" ) // NetworkContainer Prefixes @@ -197,16 +198,6 @@ type GetNetworkContainerResponse struct { AllowNCToHostCommunication bool } -type GetIPConfigRequest struct { - DesiredIPAddress string - OrchestratorContext json.RawMessage -} - -type GetIPConfigResponse struct { - PodIpInfo PodIpInfo - Response Response -} - // DeleteNetworkContainerRequest specifies the details about the request to delete a specifc network container. type PodIpInfo struct { PodIPConfig IPSubnet @@ -221,6 +212,31 @@ type HostIPInfo struct { Subnet string } +type IPConfigRequest struct { + DesiredIPAddress string + OrchestratorContext json.RawMessage +} + +type IPConfigResponse struct { + PodIpInfo PodIpInfo + Response Response +} + +type GetIPAddressesRequest struct { + IPConfigStateFilter []string +} + +type GetIPAddressStateResponse struct { + IPAddresses []IPAddressState + Response Response +} + +// Only used in the GetIPConfig API to return IP's that match a filter +type IPAddressState struct { + IPAddress string + State string +} + // DeleteNetworkContainerRequest specifies the details about the request to delete a specifc network container. type DeleteNetworkContainerRequest struct { NetworkContainerid string diff --git a/cns/cnsclient/cli.go b/cns/cnsclient/cli.go new file mode 100644 index 0000000000..9c4172ec64 --- /dev/null +++ b/cns/cnsclient/cli.go @@ -0,0 +1,92 @@ +package cnsclient + +import ( + "fmt" + "net" + "sort" + + "github.com/Azure/azure-container-networking/cns" + acn "github.com/Azure/azure-container-networking/common" +) + +var ( + getArg = "get" + getAvailableArg = "Available" + getAllocatedArg = "Allocated" + getAllArg = "All" + + releaseArg = "release" +) + +func HandleCNSFlags(cmd, arg string) { + var ip net.IP + + interfaces, _ := net.Interfaces() + for _, iface := range interfaces { + addrs, _ := iface.Addrs() + for _, address := range addrs { + if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil { + ip = ipnet.IP + } + } + } + + cnsurl := "http://" + ip.String() + ":10090" + cnsClient, _ := InitCnsClient(cnsurl) + switch cmd { + case getArg: + getCmd(cnsClient, arg) + default: + fmt.Printf("No debug cmd supplied, options are: %v", getArg) + } +} + +func getCmd(client *CNSClient, arg string) { + switch arg { + case getAvailableArg: + fmt.Println(getAvailableArg) + addr, err := client.GetIPAddressesMatchingStates(cns.Available) + if err != nil { + fmt.Println(err) + return + } + printIPAddresses(addr) + + case getAllocatedArg: + fmt.Println(getAllocatedArg) + addr, err := client.GetIPAddressesMatchingStates(cns.Allocated) + if err != nil { + fmt.Println(err) + return + } + printIPAddresses(addr) + + case getAllArg: + fmt.Println(getAllArg) + addr, err := client.GetIPAddressesMatchingStates(cns.Allocated, cns.Available) + if err != nil { + fmt.Println(err) + return + } + printIPAddresses(addr) + default: + fmt.Println("argument supplied for the get cmd, use the '%v' flag", acn.OptDebugCmdAlias) + } +} + +func printIPAddresses(addrSlice []cns.IPAddressState) { + + sort.Slice(addrSlice, func(i, j int) bool { + if addrSlice[i].IPAddress < addrSlice[j].IPAddress { + return true + } + if addrSlice[i].IPAddress > addrSlice[j].IPAddress { + return false + } + return addrSlice[i].IPAddress < addrSlice[j].IPAddress + }) + + for _, addr := range addrSlice { + fmt.Printf("%v\n", addr) + } +} diff --git a/cns/cnsclient/cnsclient.go b/cns/cnsclient/cnsclient.go index 65b74feb27..124717f4e1 100644 --- a/cns/cnsclient/cnsclient.go +++ b/cns/cnsclient/cnsclient.go @@ -209,11 +209,11 @@ func (cnsClient *CNSClient) DeleteHostNCApipaEndpoint(networkContainerID string) } // RequestIPAddress calls the requestIPAddress in CNS -func (cnsClient *CNSClient) RequestIPAddress(orchestratorContext []byte) (*cns.GetIPConfigResponse, error) { +func (cnsClient *CNSClient) RequestIPAddress(orchestratorContext []byte) (*cns.IPConfigResponse, error) { var ( err error res *http.Response - response *cns.GetIPConfigResponse + response *cns.IPConfigResponse ) defer func() { @@ -316,3 +316,55 @@ func (cnsClient *CNSClient) ReleaseIPAddress(orchestratorContext []byte) error { return err } + +// GetIPAddressesWithStates takes a variadic number of string parameters, to get all IP Addresses matching a number of states +// usage GetIPAddressesWithStates(cns.Available, cns.Allocated) +func (cnsClient *CNSClient) GetIPAddressesMatchingStates(StateFilter ...string) ([]cns.IPAddressState, error) { + var ( + resp cns.GetIPAddressStateResponse + err error + res *http.Response + body bytes.Buffer + ) + + httpc := &http.Client{} + url := cnsClient.connectionURL + cns.GetIPAddresses + log.Printf("GetIPAddressesMatchingStates url %v", url) + + payload := &cns.GetIPAddressesRequest{ + IPConfigStateFilter: StateFilter, + } + + err = json.NewEncoder(&body).Encode(payload) + if err != nil { + log.Errorf("encoding json failed with %v", err) + return resp.IPAddresses, err + } + + res, err = httpc.Post(url, contentTypeJSON, &body) + if err != nil { + log.Errorf("[Azure CNSClient] HTTP Post returned error %v", err.Error()) + return resp.IPAddresses, err + } + + defer res.Body.Close() + + if res.StatusCode != http.StatusOK { + errMsg := fmt.Sprintf("[Azure CNSClient] GetIPAddressesMatchingStates invalid http status code: %v", res.StatusCode) + log.Errorf(errMsg) + return resp.IPAddresses, fmt.Errorf(errMsg) + } + + err = json.NewDecoder(res.Body).Decode(&resp) + if err != nil { + log.Errorf("[Azure CNSClient] Error received while parsing GetIPAddressesMatchingStates response resp:%v err:%v", res.Body, err.Error()) + return resp.IPAddresses, err + } + + if resp.Response.ReturnCode != 0 { + log.Errorf("[Azure CNSClient] GetIPAddressesMatchingStates received error response :%v", resp.Response.Message) + return resp.IPAddresses, fmt.Errorf(resp.Response.Message) + } + + return resp.IPAddresses, err +} diff --git a/cns/cnsclient/cnsclient_test.go b/cns/cnsclient/cnsclient_test.go index 372f134e48..9c3f55b0fd 100644 --- a/cns/cnsclient/cnsclient_test.go +++ b/cns/cnsclient/cnsclient_test.go @@ -71,7 +71,7 @@ func addTestStateToRestServer(t *testing.T, secondaryIps []string) { } } -func getIPNetFromResponse(resp *cns.GetIPConfigResponse) (net.IPNet, error) { +func getIPNetFromResponse(resp *cns.IPConfigResponse) (net.IPNet, error) { var ( resultIPnet net.IPNet err error diff --git a/cns/restserver/internalapi.go b/cns/restserver/internalapi.go index 645f28b27a..d9b2619668 100644 --- a/cns/restserver/internalapi.go +++ b/cns/restserver/internalapi.go @@ -177,7 +177,7 @@ func (service *HTTPRestService) ReconcileNCState(ncRequest *cns.CreateNetworkCon } jsonContext, _ := json.Marshal(kubernetesPodInfo) - ipconfigRequest := cns.GetIPConfigRequest{ + ipconfigRequest := cns.IPConfigRequest{ DesiredIPAddress: secIpConfig.IPAddress, OrchestratorContext: jsonContext, } diff --git a/cns/restserver/ipam.go b/cns/restserver/ipam.go index 26b52799af..e950b0a133 100644 --- a/cns/restserver/ipam.go +++ b/cns/restserver/ipam.go @@ -43,7 +43,7 @@ func (service *HTTPRestService) requestIPConfigHandler(w http.ResponseWriter, r Message: returnMessage, } - reserveResp := &cns.GetIPConfigResponse{ + reserveResp := &cns.IPConfigResponse{ Response: resp, } reserveResp.PodIpInfo = podIpInfo @@ -54,7 +54,8 @@ func (service *HTTPRestService) requestIPConfigHandler(w http.ResponseWriter, r func (service *HTTPRestService) releaseIPConfigHandler(w http.ResponseWriter, r *http.Request) { var ( - req cns.GetIPConfigRequest + podInfo cns.KubernetesPodInfo + req cns.IPConfigRequest statusCode int returnMessage string ) @@ -127,7 +128,59 @@ func (service *HTTPRestService) GetPendingProgramIPConfigs() []cns.IPConfigurati }) } -func (service *HTTPRestService) GetAllocatedIPConfigs() []cns.IPConfigurationStatus { +func (service *HTTPRestService) getIPAddressesHandler(w http.ResponseWriter, r *http.Request) { + var ( + req cns.GetIPAddressesRequest + resp cns.GetIPAddressStateResponse + statusCode int + returnMessage string + ) + + statusCode = UnexpectedError + + err := service.Listener.Decode(w, r, &req) + logger.Request(service.Name, &req, err) + if err != nil { + returnMessage = err.Error() + return + } + + defer func() { + + if err != nil { + resp.Response.ReturnCode = statusCode + resp.Response.Message = returnMessage + } + + err = service.Listener.Encode(w, &resp) + logger.Response(service.Name, resp, resp.Response.ReturnCode, ReturnCodeToString(resp.Response.ReturnCode), err) + }() + + resp.IPAddresses = make([]cns.IPAddressState, 0) + for _, podstate := range req.IPConfigStateFilter { + resp.IPAddresses = append(resp.IPAddresses, filterIPConfigsWithState(service.PodIPConfigState, podstate, func(ipconfig ipConfigurationStatus, state string) bool { + return ipconfig.State == podstate + })...) + } + + return +} + +func filterIPConfigsWithState(toBeAdded map[string]ipConfigurationStatus, state string, f func(ipConfigurationStatus, string) bool) []cns.IPAddressState { + vsf := make([]cns.IPAddressState, 0) + for _, v := range toBeAdded { + if f(v, state) { + ip := cns.IPAddressState{ + IPAddress: v.IPSubnet.IPAddress, + State: v.State, + } + vsf = append(vsf, ip) + } + } + return vsf +} + +func (service *HTTPRestService) GetAllocatedIPConfigs() []ipConfigurationStatus { service.RLock() defer service.RUnlock() return filterIPConfigMap(service.PodIPConfigState, func(ipconfig cns.IPConfigurationStatus) bool { diff --git a/cns/restserver/ipam_test.go b/cns/restserver/ipam_test.go index f1a280eea3..fc8d30e55b 100644 --- a/cns/restserver/ipam_test.go +++ b/cns/restserver/ipam_test.go @@ -172,7 +172,7 @@ func TestIPAMGetAvailableIPConfig(t *testing.T) { } UpdatePodIpConfigState(t, svc, ipconfigs) - req := cns.GetIPConfigRequest{} + req := cns.IPConfigRequest{} b, _ := json.Marshal(testPod1Info) req.OrchestratorContext = b @@ -207,7 +207,7 @@ func TestIPAMGetNextAvailableIPConfig(t *testing.T) { t.Fatalf("Expected to not fail adding IP's to state: %+v", err) } - req := cns.GetIPConfigRequest{} + req := cns.IPConfigRequest{} b, _ := json.Marshal(testPod2Info) req.OrchestratorContext = b @@ -236,7 +236,7 @@ func TestIPAMGetAlreadyAllocatedIPConfigForSamePod(t *testing.T) { t.Fatalf("Expected to not fail adding IP's to state: %+v", err) } - req := cns.GetIPConfigRequest{} + req := cns.IPConfigRequest{} b, _ := json.Marshal(testPod1Info) req.OrchestratorContext = b @@ -266,7 +266,7 @@ func TestIPAMAttemptToRequestIPNotFoundInPool(t *testing.T) { t.Fatalf("Expected to not fail adding IP's to state: %+v", err) } - req := cns.GetIPConfigRequest{} + req := cns.IPConfigRequest{} b, _ := json.Marshal(testPod2Info) req.OrchestratorContext = b req.DesiredIPAddress = testIP2 @@ -291,7 +291,7 @@ func TestIPAMGetDesiredIPConfigWithSpecfiedIP(t *testing.T) { t.Fatalf("Expected to not fail adding IP's to state: %+v", err) } - req := cns.GetIPConfigRequest{} + req := cns.IPConfigRequest{} b, _ := json.Marshal(testPod1Info) req.OrchestratorContext = b req.DesiredIPAddress = testIP1 @@ -323,7 +323,7 @@ func TestIPAMFailToGetDesiredIPConfigWithAlreadyAllocatedSpecfiedIP(t *testing.T } // request the already allocated ip with a new context - req := cns.GetIPConfigRequest{} + req := cns.IPConfigRequest{} b, _ := json.Marshal(testPod2Info) req.OrchestratorContext = b req.DesiredIPAddress = testIP1 @@ -351,7 +351,7 @@ func TestIPAMFailToGetIPWhenAllIPsAreAllocated(t *testing.T) { } // request the already allocated ip with a new context - req := cns.GetIPConfigRequest{} + req := cns.IPConfigRequest{} b, _ := json.Marshal(testPod3Info) req.OrchestratorContext = b @@ -382,7 +382,7 @@ func TestIPAMRequestThenReleaseThenRequestAgain(t *testing.T) { desiredIpAddress := testIP1 // Use TestPodInfo2 to request TestIP1, which has already been allocated - req := cns.GetIPConfigRequest{} + req := cns.IPConfigRequest{} b, _ := json.Marshal(testPod2Info) req.OrchestratorContext = b req.DesiredIPAddress = desiredIpAddress @@ -399,7 +399,7 @@ func TestIPAMRequestThenReleaseThenRequestAgain(t *testing.T) { } // Rerequest - req = cns.GetIPConfigRequest{} + req = cns.IPConfigRequest{} b, _ = json.Marshal(testPod2Info) req.OrchestratorContext = b req.DesiredIPAddress = desiredIpAddress @@ -491,7 +491,7 @@ func TestAvailableIPConfigs(t *testing.T) { allocatedIps := svc.GetAllocatedIPConfigs() validateIpState(t, allocatedIps, desiredAllocatedIpConfigs) - req := cns.GetIPConfigRequest{} + req := cns.IPConfigRequest{} b, _ := json.Marshal(testPod1Info) req.OrchestratorContext = b req.DesiredIPAddress = state1.IPAddress diff --git a/cns/restserver/restserver.go b/cns/restserver/restserver.go index cce2494743..f92d5414f5 100644 --- a/cns/restserver/restserver.go +++ b/cns/restserver/restserver.go @@ -176,6 +176,7 @@ func (service *HTTPRestService) Start(config *common.ServiceConfig) error { listener.AddHandler(cns.UnpublishNetworkContainer, service.unpublishNetworkContainer) listener.AddHandler(cns.RequestIPConfig, service.requestIPConfigHandler) listener.AddHandler(cns.ReleaseIPConfig, service.releaseIPConfigHandler) + listener.AddHandler(cns.GetIPAddresses, service.getIPAddressesHandler) // handlers for v0.2 listener.AddHandler(cns.V2Prefix+cns.SetEnvironmentPath, service.setEnvironment) diff --git a/cns/service/main.go b/cns/service/main.go index 330ebf1391..5d185d699f 100644 --- a/cns/service/main.go +++ b/cns/service/main.go @@ -23,6 +23,7 @@ import ( "github.com/Azure/azure-container-networking/cnm/ipam" "github.com/Azure/azure-container-networking/cnm/network" "github.com/Azure/azure-container-networking/cns" + "github.com/Azure/azure-container-networking/cns/cnsclient" "github.com/Azure/azure-container-networking/cns/common" "github.com/Azure/azure-container-networking/cns/configuration" "github.com/Azure/azure-container-networking/cns/hnsclient" @@ -222,6 +223,20 @@ var args = acn.ArgumentList{ Type: "bool", DefaultValue: false, }, + { + Name: acn.OptDebugCmd, + Shorthand: acn.OptDebugCmdAlias, + Description: "Debug flag to retrieve IPconfigs, available values: allocated, available, all", + Type: "string", + DefaultValue: "", + }, + { + Name: acn.OptDebugArg, + Shorthand: acn.OptDebugArgAlias, + Description: "Argument flag to be paired with the 'debugcmd' flag.", + Type: "string", + DefaultValue: "", + }, } // Prints description and version information. @@ -294,6 +309,8 @@ func main() { privateEndpoint := acn.GetArg(acn.OptPrivateEndpoint).(string) infravnet := acn.GetArg(acn.OptInfrastructureNetworkID).(string) nodeID := acn.GetArg(acn.OptNodeID).(string) + clientDebugCmd := acn.GetArg(acn.OptDebugCmd).(string) + clientDebugArg := acn.GetArg(acn.OptDebugArg).(string) if vers { printVersion() @@ -314,6 +331,11 @@ func main() { // Create logging provider. logger.InitLogger(name, logLevel, logTarget, logDirectory) + if clientDebugCmd != "" { + cnsclient.HandleCNSFlags(clientDebugCmd, clientDebugArg) + os.Exit(0) + } + if !telemetryEnabled { logger.Errorf("[Azure CNS] Cannot disable telemetry via cmdline. Update cns_config.json to disable telemetry.") } diff --git a/common/config.go b/common/config.go index 1239a04e96..c380093ff8 100644 --- a/common/config.go +++ b/common/config.go @@ -114,4 +114,12 @@ const ( // Managed mode OptManaged = "managed" OptManagedAlias = "m" + + // Client mode, get allocated ipconfigs + OptDebugCmd = "debugcmd" + OptDebugCmdAlias = "cmd" + + // Client mode, get allocated ipconfigs + OptDebugArg = "debugarg" + OptDebugArgAlias = "darg" ) From 1afeb358dab7b2ef7e855233e4ec4ca23fae0142 Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Thu, 13 Aug 2020 21:25:11 -0700 Subject: [PATCH 02/10] update tests --- cns/cnsclient/cli.go | 6 ++++-- cns/cnsclient/cnsclient.go | 4 ++-- cns/cnsclient/cnsclient_test.go | 13 +++++++++++++ cns/restserver/ipam.go | 3 +-- cns/restserver/util.go | 2 +- 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/cns/cnsclient/cli.go b/cns/cnsclient/cli.go index 9c4172ec64..22a4d748fa 100644 --- a/cns/cnsclient/cli.go +++ b/cns/cnsclient/cli.go @@ -50,6 +50,7 @@ func getCmd(client *CNSClient, arg string) { fmt.Println(err) return } + printIPAddresses(addr) case getAllocatedArg: @@ -59,6 +60,7 @@ func getCmd(client *CNSClient, arg string) { fmt.Println(err) return } + printIPAddresses(addr) case getAllArg: @@ -68,14 +70,14 @@ func getCmd(client *CNSClient, arg string) { fmt.Println(err) return } + printIPAddresses(addr) default: - fmt.Println("argument supplied for the get cmd, use the '%v' flag", acn.OptDebugCmdAlias) + fmt.Printf("argument supplied for the get cmd, use the '%v' flag", acn.OptDebugCmdAlias) } } func printIPAddresses(addrSlice []cns.IPAddressState) { - sort.Slice(addrSlice, func(i, j int) bool { if addrSlice[i].IPAddress < addrSlice[j].IPAddress { return true diff --git a/cns/cnsclient/cnsclient.go b/cns/cnsclient/cnsclient.go index 124717f4e1..0682f05350 100644 --- a/cns/cnsclient/cnsclient.go +++ b/cns/cnsclient/cnsclient.go @@ -227,7 +227,7 @@ func (cnsClient *CNSClient) RequestIPAddress(orchestratorContext []byte) (*cns.I httpc := &http.Client{} url := cnsClient.connectionURL + cns.RequestIPConfig - payload := &cns.GetIPConfigRequest{ + payload := &cns.IPConfigRequest{ OrchestratorContext: orchestratorContext, } @@ -277,7 +277,7 @@ func (cnsClient *CNSClient) ReleaseIPAddress(orchestratorContext []byte) error { url := cnsClient.connectionURL + cns.ReleaseIPConfig log.Printf("ReleaseIPAddress url %v", url) - payload := &cns.GetIPConfigRequest{ + payload := &cns.IPConfigRequest{ OrchestratorContext: orchestratorContext, } diff --git a/cns/cnsclient/cnsclient_test.go b/cns/cnsclient/cnsclient_test.go index 9c3f55b0fd..0ef9e065f6 100644 --- a/cns/cnsclient/cnsclient_test.go +++ b/cns/cnsclient/cnsclient_test.go @@ -222,4 +222,17 @@ func TestCNSClientRequestAndRelease(t *testing.T) { if err != nil { t.Fatalf("Expected to not fail when releasing IP reservation found with context: %+v", err) } + + ipaddresses, err = cnsClient.GetIPAddressesMatchingStates(cns.Available) + if err != nil { + t.Fatalf("Get allocated IP addresses failed %+v", err) + } + + if len(ipaddresses) != 1 { + t.Fatalf("Number of available IP addresses expected to be 1, actual %+v", ipaddresses) + } + + if ipaddresses[0].IPAddress != desiredIpAddress && ipaddresses[0].State != cns.Available { + t.Fatalf("Available IP address does not match expected, address state: %+v", ipaddresses) + } } diff --git a/cns/restserver/ipam.go b/cns/restserver/ipam.go index e950b0a133..79472100e4 100644 --- a/cns/restserver/ipam.go +++ b/cns/restserver/ipam.go @@ -54,7 +54,6 @@ func (service *HTTPRestService) requestIPConfigHandler(w http.ResponseWriter, r func (service *HTTPRestService) releaseIPConfigHandler(w http.ResponseWriter, r *http.Request) { var ( - podInfo cns.KubernetesPodInfo req cns.IPConfigRequest statusCode int returnMessage string @@ -171,7 +170,7 @@ func filterIPConfigsWithState(toBeAdded map[string]ipConfigurationStatus, state for _, v := range toBeAdded { if f(v, state) { ip := cns.IPAddressState{ - IPAddress: v.IPSubnet.IPAddress, + IPAddress: v.IPAddress, State: v.State, } vsf = append(vsf, ip) diff --git a/cns/restserver/util.go b/cns/restserver/util.go index 645aa06d62..30bf8da94d 100644 --- a/cns/restserver/util.go +++ b/cns/restserver/util.go @@ -625,7 +625,7 @@ func (service *HTTPRestService) SendNCSnapShotPeriodically(ncSnapshotIntervalInM } } -func (service *HTTPRestService) validateIpConfigRequest(ipConfigRequest cns.GetIPConfigRequest) (cns.KubernetesPodInfo, int, string) { +func (service *HTTPRestService) validateIpConfigRequest(ipConfigRequest cns.IPConfigRequest) (cns.KubernetesPodInfo, int, string) { var podInfo cns.KubernetesPodInfo if service.state.OrchestratorType != cns.KubernetesCRD { From fe55a4a789f237727d9ae0654dd5e084532c000d Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Fri, 14 Aug 2020 09:42:06 -0700 Subject: [PATCH 03/10] fixed nits --- cns/NetworkContainerContract.go | 6 +++++- cns/cnsclient/cli.go | 8 +++++--- cns/restserver/ipam.go | 18 +++++++++++++++--- cns/service/main.go | 2 +- common/config.go | 4 ++-- 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/cns/NetworkContainerContract.go b/cns/NetworkContainerContract.go index 7b1e8c6e71..cfca0c641a 100644 --- a/cns/NetworkContainerContract.go +++ b/cns/NetworkContainerContract.go @@ -217,21 +217,25 @@ type IPConfigRequest struct { OrchestratorContext json.RawMessage } +// IPConfigResponse is used in CNS IPAM mode as a response to CNI ADD type IPConfigResponse struct { PodIpInfo PodIpInfo Response Response } +// GetIPAddressesRequest is used in CNS IPAM mode to get the states of IPConfigs +// The IPConfigStateFilter is a slice of IP's to fetch from CNS that match those states type GetIPAddressesRequest struct { IPConfigStateFilter []string } +// GetIPAddressStateResponse is used in CNS IPAM mode as a response to get IP address state type GetIPAddressStateResponse struct { IPAddresses []IPAddressState Response Response } -// Only used in the GetIPConfig API to return IP's that match a filter +// IPAddressState Only used in the GetIPConfig API to return IP's that match a filter type IPAddressState struct { IPAddress string State string diff --git a/cns/cnsclient/cli.go b/cns/cnsclient/cli.go index 22a4d748fa..b347d398e6 100644 --- a/cns/cnsclient/cli.go +++ b/cns/cnsclient/cli.go @@ -18,9 +18,10 @@ var ( releaseArg = "release" ) -func HandleCNSFlags(cmd, arg string) { +func HandleCNSClientCommands(cmd, arg string) { var ip net.IP + // retrieve the primary interface that CNS is listening on interfaces, _ := net.Interfaces() for _, iface := range interfaces { addrs, _ := iface.Addrs() @@ -52,7 +53,6 @@ func getCmd(client *CNSClient, arg string) { } printIPAddresses(addr) - case getAllocatedArg: fmt.Println(getAllocatedArg) addr, err := client.GetIPAddressesMatchingStates(cns.Allocated) @@ -62,7 +62,6 @@ func getCmd(client *CNSClient, arg string) { } printIPAddresses(addr) - case getAllArg: fmt.Println(getAllArg) addr, err := client.GetIPAddressesMatchingStates(cns.Allocated, cns.Available) @@ -77,14 +76,17 @@ func getCmd(client *CNSClient, arg string) { } } +// Sort the addresses based on IP, then write to stdout func printIPAddresses(addrSlice []cns.IPAddressState) { sort.Slice(addrSlice, func(i, j int) bool { if addrSlice[i].IPAddress < addrSlice[j].IPAddress { return true } + if addrSlice[i].IPAddress > addrSlice[j].IPAddress { return false } + return addrSlice[i].IPAddress < addrSlice[j].IPAddress }) diff --git a/cns/restserver/ipam.go b/cns/restserver/ipam.go index 79472100e4..38b915105d 100644 --- a/cns/restserver/ipam.go +++ b/cns/restserver/ipam.go @@ -145,7 +145,6 @@ func (service *HTTPRestService) getIPAddressesHandler(w http.ResponseWriter, r * } defer func() { - if err != nil { resp.Response.ReturnCode = statusCode resp.Response.Message = returnMessage @@ -155,9 +154,10 @@ func (service *HTTPRestService) getIPAddressesHandler(w http.ResponseWriter, r * logger.Response(service.Name, resp, resp.Response.ReturnCode, ReturnCodeToString(resp.Response.ReturnCode), err) }() + // Get all IPConfigs matching a state, and append to a slice of IPAddressState resp.IPAddresses = make([]cns.IPAddressState, 0) for _, podstate := range req.IPConfigStateFilter { - resp.IPAddresses = append(resp.IPAddresses, filterIPConfigsWithState(service.PodIPConfigState, podstate, func(ipconfig ipConfigurationStatus, state string) bool { + resp.IPAddresses = append(resp.IPAddresses, filterIPConfigsMatchingState(service.PodIPConfigState, podstate, func(ipconfig ipConfigurationStatus, state string) bool { return ipconfig.State == podstate })...) } @@ -165,7 +165,8 @@ func (service *HTTPRestService) getIPAddressesHandler(w http.ResponseWriter, r * return } -func filterIPConfigsWithState(toBeAdded map[string]ipConfigurationStatus, state string, f func(ipConfigurationStatus, string) bool) []cns.IPAddressState { +// filter the ipconfigs in CNS matching a state (Available, Allocated, etc.) and return in a slice +func filterIPConfigsMatchingState(toBeAdded map[string]ipConfigurationStatus, state string, f func(ipConfigurationStatus, string) bool) []cns.IPAddressState { vsf := make([]cns.IPAddressState, 0) for _, v := range toBeAdded { if f(v, state) { @@ -179,6 +180,17 @@ func filterIPConfigsWithState(toBeAdded map[string]ipConfigurationStatus, state return vsf } +// filter ipconfigs based on predicate +func filterIPConfigs(toBeAdded map[string]ipConfigurationStatus, f func(ipConfigurationStatus) bool) []ipConfigurationStatus { + vsf := make([]ipConfigurationStatus, 0) + for _, v := range toBeAdded { + if f(v) { + vsf = append(vsf, v) + } + } + return vsf +} + func (service *HTTPRestService) GetAllocatedIPConfigs() []ipConfigurationStatus { service.RLock() defer service.RUnlock() diff --git a/cns/service/main.go b/cns/service/main.go index 5d185d699f..09cd4ee502 100644 --- a/cns/service/main.go +++ b/cns/service/main.go @@ -332,7 +332,7 @@ func main() { logger.InitLogger(name, logLevel, logTarget, logDirectory) if clientDebugCmd != "" { - cnsclient.HandleCNSFlags(clientDebugCmd, clientDebugArg) + cnsclient.HandleCNSClientCommands(clientDebugCmd, clientDebugArg) os.Exit(0) } diff --git a/common/config.go b/common/config.go index c380093ff8..024349a4ce 100644 --- a/common/config.go +++ b/common/config.go @@ -115,11 +115,11 @@ const ( OptManaged = "managed" OptManagedAlias = "m" - // Client mode, get allocated ipconfigs + // Client mode, cmd OptDebugCmd = "debugcmd" OptDebugCmdAlias = "cmd" - // Client mode, get allocated ipconfigs + // Client mode, args for cmd OptDebugArg = "debugarg" OptDebugArgAlias = "darg" ) From 494e789576dd9d27899cb13fd025d057abd926f3 Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Fri, 14 Aug 2020 16:41:13 -0700 Subject: [PATCH 04/10] feedback --- cns/cnsclient/cli.go | 43 ++++++++++++++++++++++++++++++++++-------- cns/restserver/ipam.go | 30 +++++++++++++++-------------- cns/service/main.go | 6 +++++- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/cns/cnsclient/cli.go b/cns/cnsclient/cli.go index b347d398e6..ea61dbf856 100644 --- a/cns/cnsclient/cli.go +++ b/cns/cnsclient/cli.go @@ -10,36 +10,63 @@ import ( ) var ( - getArg = "get" + getArg = "get" + + availableCmds = []string{ + getArg, + } + getAvailableArg = "Available" getAllocatedArg = "Allocated" getAllArg = "All" + getFlags = []string{ + getAvailableArg, + getAllocatedArg, + getAllocatedArg, + } + releaseArg = "release" + + eth0InterfaceName = "eth0" + azure0InterfaceName = "azure0" ) -func HandleCNSClientCommands(cmd, arg string) { +func HandleCNSClientCommands(cmd, arg string) error { var ip net.IP // retrieve the primary interface that CNS is listening on interfaces, _ := net.Interfaces() +FindIP: for _, iface := range interfaces { - addrs, _ := iface.Addrs() - for _, address := range addrs { - if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil { - ip = ipnet.IP + if iface.Name == eth0InterfaceName || iface.Name == azure0InterfaceName { + addrs, _ := iface.Addrs() + for _, address := range addrs { + if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil { + ip = ipnet.IP + break FindIP + } } } } + if ip == nil { + return fmt.Errorf("Primary IP not found") + } + cnsurl := "http://" + ip.String() + ":10090" - cnsClient, _ := InitCnsClient(cnsurl) + cnsClient, err := InitCnsClient(cnsurl) + if err != nil { + return err + } + switch cmd { case getArg: getCmd(cnsClient, arg) default: - fmt.Printf("No debug cmd supplied, options are: %v", getArg) + return fmt.Errorf("No debug cmd supplied, options are: %v", getArg) } + return nil } func getCmd(client *CNSClient, arg string) { diff --git a/cns/restserver/ipam.go b/cns/restserver/ipam.go index 38b915105d..5fbdd94f0d 100644 --- a/cns/restserver/ipam.go +++ b/cns/restserver/ipam.go @@ -57,17 +57,11 @@ func (service *HTTPRestService) releaseIPConfigHandler(w http.ResponseWriter, r req cns.IPConfigRequest statusCode int returnMessage string + err error ) statusCode = UnexpectedError - err := service.Listener.Decode(w, r, &req) - logger.Request(service.Name, &req, err) - if err != nil { - returnMessage = err.Error() - return - } - defer func() { resp := cns.Response{} @@ -80,6 +74,13 @@ func (service *HTTPRestService) releaseIPConfigHandler(w http.ResponseWriter, r logger.Response(service.Name, resp, resp.ReturnCode, ReturnCodeToString(resp.ReturnCode), err) }() + err = service.Listener.Decode(w, r, &req) + logger.Request(service.Name, &req, err) + if err != nil { + returnMessage = err.Error() + return + } + podInfo, statusCode, returnMessage := service.validateIpConfigRequest(req) if err = service.releaseIPConfig(podInfo); err != nil { @@ -133,17 +134,11 @@ func (service *HTTPRestService) getIPAddressesHandler(w http.ResponseWriter, r * resp cns.GetIPAddressStateResponse statusCode int returnMessage string + err error ) statusCode = UnexpectedError - err := service.Listener.Decode(w, r, &req) - logger.Request(service.Name, &req, err) - if err != nil { - returnMessage = err.Error() - return - } - defer func() { if err != nil { resp.Response.ReturnCode = statusCode @@ -154,6 +149,13 @@ func (service *HTTPRestService) getIPAddressesHandler(w http.ResponseWriter, r * logger.Response(service.Name, resp, resp.Response.ReturnCode, ReturnCodeToString(resp.Response.ReturnCode), err) }() + err = service.Listener.Decode(w, r, &req) + logger.Request(service.Name, &req, err) + if err != nil { + returnMessage = err.Error() + return + } + // Get all IPConfigs matching a state, and append to a slice of IPAddressState resp.IPAddresses = make([]cns.IPAddressState, 0) for _, podstate := range req.IPConfigStateFilter { diff --git a/cns/service/main.go b/cns/service/main.go index 09cd4ee502..f4c757f42d 100644 --- a/cns/service/main.go +++ b/cns/service/main.go @@ -332,7 +332,11 @@ func main() { logger.InitLogger(name, logLevel, logTarget, logDirectory) if clientDebugCmd != "" { - cnsclient.HandleCNSClientCommands(clientDebugCmd, clientDebugArg) + err := cnsclient.HandleCNSClientCommands(clientDebugCmd, clientDebugArg) + if err != nil { + fmt.Println(err) + os.Exit(1) + } os.Exit(0) } From 8535a0432aebf054eae0e5ef2317b0f17e3bf301 Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Tue, 1 Sep 2020 15:51:47 -0700 Subject: [PATCH 05/10] remove merge artifacts --- cns/cnsclient/cnsclient_test.go | 2 +- cns/restserver/ipam.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cns/cnsclient/cnsclient_test.go b/cns/cnsclient/cnsclient_test.go index 0ef9e065f6..aeae417033 100644 --- a/cns/cnsclient/cnsclient_test.go +++ b/cns/cnsclient/cnsclient_test.go @@ -223,7 +223,7 @@ func TestCNSClientRequestAndRelease(t *testing.T) { t.Fatalf("Expected to not fail when releasing IP reservation found with context: %+v", err) } - ipaddresses, err = cnsClient.GetIPAddressesMatchingStates(cns.Available) + ipaddresses, err := cnsClient.GetIPAddressesMatchingStates(cns.Available) if err != nil { t.Fatalf("Get allocated IP addresses failed %+v", err) } diff --git a/cns/restserver/ipam.go b/cns/restserver/ipam.go index 5fbdd94f0d..a58e02cae6 100644 --- a/cns/restserver/ipam.go +++ b/cns/restserver/ipam.go @@ -17,7 +17,7 @@ import ( func (service *HTTPRestService) requestIPConfigHandler(w http.ResponseWriter, r *http.Request) { var ( err error - ipconfigRequest cns.GetIPConfigRequest + ipconfigRequest cns.IPConfigRequest podIpInfo cns.PodIpInfo returnCode int returnMessage string @@ -366,7 +366,7 @@ func (service *HTTPRestService) AllocateAnyAvailableIPConfig(podInfo cns.Kuberne } // If IPConfig is already allocated for pod, it returns that else it returns one of the available ipconfigs. -func requestIPConfigHelper(service *HTTPRestService, req cns.GetIPConfigRequest) (cns.PodIpInfo, error) { +func requestIPConfigHelper(service *HTTPRestService, req cns.IPConfigRequest) (cns.PodIpInfo, error) { var ( podInfo cns.KubernetesPodInfo podIpInfo cns.PodIpInfo From f2bf85c29f6fa5f8b3f427d768329a0c533445bc Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Tue, 1 Sep 2020 16:08:36 -0700 Subject: [PATCH 06/10] rebase artifacts --- cns/restserver/ipam.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cns/restserver/ipam.go b/cns/restserver/ipam.go index a58e02cae6..bfc2a956c5 100644 --- a/cns/restserver/ipam.go +++ b/cns/restserver/ipam.go @@ -159,7 +159,7 @@ func (service *HTTPRestService) getIPAddressesHandler(w http.ResponseWriter, r * // Get all IPConfigs matching a state, and append to a slice of IPAddressState resp.IPAddresses = make([]cns.IPAddressState, 0) for _, podstate := range req.IPConfigStateFilter { - resp.IPAddresses = append(resp.IPAddresses, filterIPConfigsMatchingState(service.PodIPConfigState, podstate, func(ipconfig ipConfigurationStatus, state string) bool { + resp.IPAddresses = append(resp.IPAddresses, filterIPConfigsMatchingState(service.PodIPConfigState, podstate, func(ipconfig cns.IPConfigurationStatus, state string) bool { return ipconfig.State == podstate })...) } @@ -168,7 +168,7 @@ func (service *HTTPRestService) getIPAddressesHandler(w http.ResponseWriter, r * } // filter the ipconfigs in CNS matching a state (Available, Allocated, etc.) and return in a slice -func filterIPConfigsMatchingState(toBeAdded map[string]ipConfigurationStatus, state string, f func(ipConfigurationStatus, string) bool) []cns.IPAddressState { +func filterIPConfigsMatchingState(toBeAdded map[string]cns.IPConfigurationStatus, state string, f func(cns.IPConfigurationStatus, string) bool) []cns.IPAddressState { vsf := make([]cns.IPAddressState, 0) for _, v := range toBeAdded { if f(v, state) { @@ -183,8 +183,8 @@ func filterIPConfigsMatchingState(toBeAdded map[string]ipConfigurationStatus, st } // filter ipconfigs based on predicate -func filterIPConfigs(toBeAdded map[string]ipConfigurationStatus, f func(ipConfigurationStatus) bool) []ipConfigurationStatus { - vsf := make([]ipConfigurationStatus, 0) +func filterIPConfigs(toBeAdded map[string]cns.IPConfigurationStatus, f func(cns.IPConfigurationStatus) bool) []cns.IPConfigurationStatus { + vsf := make([]cns.IPConfigurationStatus, 0) for _, v := range toBeAdded { if f(v) { vsf = append(vsf, v) @@ -193,7 +193,7 @@ func filterIPConfigs(toBeAdded map[string]ipConfigurationStatus, f func(ipConfig return vsf } -func (service *HTTPRestService) GetAllocatedIPConfigs() []ipConfigurationStatus { +func (service *HTTPRestService) GetAllocatedIPConfigs() []cns.IPConfigurationStatus { service.RLock() defer service.RUnlock() return filterIPConfigMap(service.PodIPConfigState, func(ipconfig cns.IPConfigurationStatus) bool { From 0a77cf0878f8c4867959c310de0497b3b6f923bf Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Wed, 2 Sep 2020 09:39:51 -0700 Subject: [PATCH 07/10] fix missing variable rename --- cns/restserver/ipam_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cns/restserver/ipam_test.go b/cns/restserver/ipam_test.go index fc8d30e55b..b6944978ef 100644 --- a/cns/restserver/ipam_test.go +++ b/cns/restserver/ipam_test.go @@ -66,7 +66,7 @@ func NewPodState(ipaddress string, prefixLength uint8, id, ncid, state string) c } } -func requestIpAddressAndGetState(t *testing.T, req cns.GetIPConfigRequest) (cns.IPConfigurationStatus, error) { +func requestIpAddressAndGetState(t *testing.T, req cns.IPConfigRequest) (cns.IPConfigurationStatus, error) { var ( podInfo cns.KubernetesPodInfo ipState cns.IPConfigurationStatus From eedbda285bbb48b7bfd5e0dc2d32fe4f4776a057 Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Thu, 17 Sep 2020 08:05:53 -0700 Subject: [PATCH 08/10] add support for pending release --- cns/NetworkContainerContract.go | 2 +- cns/cnsclient/cli.go | 30 ++++++++++++++++++------------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/cns/NetworkContainerContract.go b/cns/NetworkContainerContract.go index cfca0c641a..3fdee87753 100644 --- a/cns/NetworkContainerContract.go +++ b/cns/NetworkContainerContract.go @@ -22,7 +22,7 @@ const ( DetachContainerFromNetwork = "/network/detachcontainerfromnetwork" RequestIPConfig = "/network/requestipconfig" ReleaseIPConfig = "/network/releaseipconfig" - GetIPAddresses = "/network/getipconfigs" + GetIPAddresses = "/debug/getipaddresses" ) // NetworkContainer Prefixes diff --git a/cns/cnsclient/cli.go b/cns/cnsclient/cli.go index ea61dbf856..24d9fee9e1 100644 --- a/cns/cnsclient/cli.go +++ b/cns/cnsclient/cli.go @@ -16,9 +16,10 @@ var ( getArg, } - getAvailableArg = "Available" - getAllocatedArg = "Allocated" - getAllArg = "All" + getAvailableArg = "Available" + getAllocatedArg = "Allocated" + getAllArg = "All" + getPendingReleaseArg = "PendingRelease" getFlags = []string{ getAvailableArg, @@ -71,33 +72,38 @@ FindIP: func getCmd(client *CNSClient, arg string) { switch arg { - case getAvailableArg: - fmt.Println(getAvailableArg) + case cns.Available: addr, err := client.GetIPAddressesMatchingStates(cns.Available) if err != nil { fmt.Println(err) return } - printIPAddresses(addr) - case getAllocatedArg: - fmt.Println(getAllocatedArg) + + case cns.Allocated: addr, err := client.GetIPAddressesMatchingStates(cns.Allocated) if err != nil { fmt.Println(err) return } - printIPAddresses(addr) + case getAllArg: - fmt.Println(getAllArg) - addr, err := client.GetIPAddressesMatchingStates(cns.Allocated, cns.Available) + addr, err := client.GetIPAddressesMatchingStates(cns.Allocated, cns.Available, cns.PendingRelease) if err != nil { fmt.Println(err) return } + printIPAddresses(addr) + case cns.PendingRelease: + addr, err := client.GetIPAddressesMatchingStates(cns.PendingRelease) + if err != nil { + fmt.Println(err) + return + } printIPAddresses(addr) + default: fmt.Printf("argument supplied for the get cmd, use the '%v' flag", acn.OptDebugCmdAlias) } @@ -118,6 +124,6 @@ func printIPAddresses(addrSlice []cns.IPAddressState) { }) for _, addr := range addrSlice { - fmt.Printf("%v\n", addr) + fmt.Printf("%+v\n", addr) } } From 3dbf8413669ac984397b51c365c2329a0e282577 Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Mon, 28 Sep 2020 12:49:33 -0700 Subject: [PATCH 09/10] feedback --- cns/cnsclient/cli.go | 89 +++++++++++++++----------------------- cns/cnsclient/cnsclient.go | 7 ++- cns/restserver/ipam.go | 21 +++++---- 3 files changed, 52 insertions(+), 65 deletions(-) diff --git a/cns/cnsclient/cli.go b/cns/cnsclient/cli.go index 24d9fee9e1..8e779321f1 100644 --- a/cns/cnsclient/cli.go +++ b/cns/cnsclient/cli.go @@ -4,33 +4,34 @@ import ( "fmt" "net" "sort" + "strings" "github.com/Azure/azure-container-networking/cns" - acn "github.com/Azure/azure-container-networking/common" ) -var ( - getArg = "get" - - availableCmds = []string{ - getArg, - } - +const ( + getCmdArg = "get" getAvailableArg = "Available" getAllocatedArg = "Allocated" getAllArg = "All" getPendingReleaseArg = "PendingRelease" + releaseArg = "release" + + eth0InterfaceName = "eth0" + azure0InterfaceName = "azure0" +) + +var ( + availableCmds = []string{ + getCmdArg, + } + getFlags = []string{ getAvailableArg, getAllocatedArg, getAllocatedArg, } - - releaseArg = "release" - - eth0InterfaceName = "eth0" - azure0InterfaceName = "azure0" ) func HandleCNSClientCommands(cmd, arg string) error { @@ -61,65 +62,45 @@ FindIP: return err } - switch cmd { - case getArg: - getCmd(cnsClient, arg) + switch { + case strings.EqualFold(getCmdArg, cmd): + return getCmd(cnsClient, arg) default: - return fmt.Errorf("No debug cmd supplied, options are: %v", getArg) + return fmt.Errorf("No debug cmd supplied, options are: %v", getCmdArg) } - return nil } -func getCmd(client *CNSClient, arg string) { +func getCmd(client *CNSClient, arg string) error { + var states []string + switch arg { case cns.Available: - addr, err := client.GetIPAddressesMatchingStates(cns.Available) - if err != nil { - fmt.Println(err) - return - } - printIPAddresses(addr) + states = append(states, cns.Available) case cns.Allocated: - addr, err := client.GetIPAddressesMatchingStates(cns.Allocated) - if err != nil { - fmt.Println(err) - return - } - printIPAddresses(addr) - - case getAllArg: - addr, err := client.GetIPAddressesMatchingStates(cns.Allocated, cns.Available, cns.PendingRelease) - if err != nil { - fmt.Println(err) - return - } - printIPAddresses(addr) + states = append(states, cns.Allocated) case cns.PendingRelease: - addr, err := client.GetIPAddressesMatchingStates(cns.PendingRelease) - if err != nil { - fmt.Println(err) - return - } - printIPAddresses(addr) + states = append(states, cns.PendingRelease) default: - fmt.Printf("argument supplied for the get cmd, use the '%v' flag", acn.OptDebugCmdAlias) + states = append(states, cns.Allocated) + states = append(states, cns.Available) + states = append(states, cns.PendingRelease) + } + + addr, err := client.GetIPAddressesMatchingStates(states...) + if err != nil { + return err } + + printIPAddresses(addr) + return nil } // Sort the addresses based on IP, then write to stdout func printIPAddresses(addrSlice []cns.IPAddressState) { sort.Slice(addrSlice, func(i, j int) bool { - if addrSlice[i].IPAddress < addrSlice[j].IPAddress { - return true - } - - if addrSlice[i].IPAddress > addrSlice[j].IPAddress { - return false - } - return addrSlice[i].IPAddress < addrSlice[j].IPAddress }) diff --git a/cns/cnsclient/cnsclient.go b/cns/cnsclient/cnsclient.go index 0682f05350..caf0474e51 100644 --- a/cns/cnsclient/cnsclient.go +++ b/cns/cnsclient/cnsclient.go @@ -327,7 +327,10 @@ func (cnsClient *CNSClient) GetIPAddressesMatchingStates(StateFilter ...string) body bytes.Buffer ) - httpc := &http.Client{} + if len(StateFilter) == 0 { + return []cns.IPAddressState{}, nil + } + url := cnsClient.connectionURL + cns.GetIPAddresses log.Printf("GetIPAddressesMatchingStates url %v", url) @@ -341,7 +344,7 @@ func (cnsClient *CNSClient) GetIPAddressesMatchingStates(StateFilter ...string) return resp.IPAddresses, err } - res, err = httpc.Post(url, contentTypeJSON, &body) + res, err = http.Post(url, contentTypeJSON, &body) if err != nil { log.Errorf("[Azure CNSClient] HTTP Post returned error %v", err.Error()) return resp.IPAddresses, err diff --git a/cns/restserver/ipam.go b/cns/restserver/ipam.go index bfc2a956c5..cdcf20f5b9 100644 --- a/cns/restserver/ipam.go +++ b/cns/restserver/ipam.go @@ -150,28 +150,31 @@ func (service *HTTPRestService) getIPAddressesHandler(w http.ResponseWriter, r * }() err = service.Listener.Decode(w, r, &req) - logger.Request(service.Name, &req, err) if err != nil { returnMessage = err.Error() return } - // Get all IPConfigs matching a state, and append to a slice of IPAddressState - resp.IPAddresses = make([]cns.IPAddressState, 0) - for _, podstate := range req.IPConfigStateFilter { - resp.IPAddresses = append(resp.IPAddresses, filterIPConfigsMatchingState(service.PodIPConfigState, podstate, func(ipconfig cns.IPConfigurationStatus, state string) bool { - return ipconfig.State == podstate - })...) + filterFunc := func(ipconfig cns.IPConfigurationStatus, states []string) bool { + for _, state := range states { + if ipconfig.State == state { + return true + } + } + return false } + // Get all IPConfigs matching a state, and append to a slice of IPAddressState + resp.IPAddresses = filterIPConfigsMatchingState(service.PodIPConfigState, req.IPConfigStateFilter, filterFunc) + return } // filter the ipconfigs in CNS matching a state (Available, Allocated, etc.) and return in a slice -func filterIPConfigsMatchingState(toBeAdded map[string]cns.IPConfigurationStatus, state string, f func(cns.IPConfigurationStatus, string) bool) []cns.IPAddressState { +func filterIPConfigsMatchingState(toBeAdded map[string]cns.IPConfigurationStatus, states []string, f func(cns.IPConfigurationStatus, []string) bool) []cns.IPAddressState { vsf := make([]cns.IPAddressState, 0) for _, v := range toBeAdded { - if f(v, state) { + if f(v, states) { ip := cns.IPAddressState{ IPAddress: v.IPAddress, State: v.State, From b506d0e632fa404b809131c83371b66fb8167afb Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Thu, 29 Oct 2020 17:16:21 -0700 Subject: [PATCH 10/10] connect to localhost --- cns/cnsclient/cli.go | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/cns/cnsclient/cli.go b/cns/cnsclient/cli.go index 8e779321f1..7aa314fe36 100644 --- a/cns/cnsclient/cli.go +++ b/cns/cnsclient/cli.go @@ -2,7 +2,6 @@ package cnsclient import ( "fmt" - "net" "sort" "strings" @@ -20,6 +19,8 @@ const ( eth0InterfaceName = "eth0" azure0InterfaceName = "azure0" + + defaultCNSURl = "http://localhost:10090" ) var ( @@ -35,29 +36,7 @@ var ( ) func HandleCNSClientCommands(cmd, arg string) error { - var ip net.IP - - // retrieve the primary interface that CNS is listening on - interfaces, _ := net.Interfaces() -FindIP: - for _, iface := range interfaces { - if iface.Name == eth0InterfaceName || iface.Name == azure0InterfaceName { - addrs, _ := iface.Addrs() - for _, address := range addrs { - if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil { - ip = ipnet.IP - break FindIP - } - } - } - } - - if ip == nil { - return fmt.Errorf("Primary IP not found") - } - - cnsurl := "http://" + ip.String() + ":10090" - cnsClient, err := InitCnsClient(cnsurl) + cnsClient, err := InitCnsClient(defaultCNSURl) if err != nil { return err }