From 5d96c7b0513b89965bb371cd8cc811833767cabc Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Thu, 3 Jun 2021 17:03:10 -0700 Subject: [PATCH 1/8] inital dump state and ipam interface update --- cni/api/api.go | 13 ++++++++ cni/cni.go | 3 ++ cni/network/invoker.go | 6 ++-- cni/network/invoker_azure.go | 5 +-- cni/network/invoker_cns.go | 25 ++++++++------ cni/network/network.go | 46 +++++++++++++++++++------ cni/network/network_test.go | 65 ++++++++++++++++++++++++++++++++---- cni/network/plugin/main.go | 8 ++++- cns/cnsclient/cnsclient.go | 10 ++---- network/endpoint_linux.go | 2 +- network/manager.go | 19 +++++++++++ network/manager_mock.go | 20 ++++++----- network/network.go | 2 +- 13 files changed, 174 insertions(+), 50 deletions(-) create mode 100644 cni/api/api.go diff --git a/cni/api/api.go b/cni/api/api.go new file mode 100644 index 0000000000..937dcdcac4 --- /dev/null +++ b/cni/api/api.go @@ -0,0 +1,13 @@ +package api + +import "net" + +type NetworkInterfaceInfo struct { + PodInterfaceID string + ContainerID string + IPAddresses []net.IPNet +} + +type AzureCNIState struct { + ContainerInterfaces map[string]NetworkInterfaceInfo +} diff --git a/cni/cni.go b/cni/cni.go index 239eb6301d..4738b3be8a 100644 --- a/cni/cni.go +++ b/cni/cni.go @@ -15,6 +15,9 @@ const ( CmdDel = "DEL" CmdUpdate = "UPDATE" + // nonstandard CNI spec command, used to dump CNI state to stdout + CmdState = "STATE" + // CNI errors. ErrRuntime = 100 diff --git a/cni/network/invoker.go b/cni/network/invoker.go index 3afc4a95d8..aceb3e242a 100644 --- a/cni/network/invoker.go +++ b/cni/network/invoker.go @@ -4,7 +4,7 @@ import ( "net" "github.com/Azure/azure-container-networking/cni" - "github.com/Azure/azure-container-networking/network" + cniSkel "github.com/containernetworking/cni/pkg/skel" cniTypesCurr "github.com/containernetworking/cni/pkg/types/current" ) @@ -14,8 +14,8 @@ import ( type IPAMInvoker interface { //Add returns two results, one IPv4, the other IPv6. - Add(nwCfg *cni.NetworkConfig, subnetPrefix *net.IPNet, options map[string]interface{}) (*cniTypesCurr.Result, *cniTypesCurr.Result, error) + Add(nwCfg *cni.NetworkConfig, args *cniSkel.CmdArgs, subnetPrefix *net.IPNet, options map[string]interface{}) (*cniTypesCurr.Result, *cniTypesCurr.Result, error) //Delete calls to the invoker source, and returns error. Returning an error here will fail the CNI Delete call. - Delete(address *net.IPNet, nwCfg *cni.NetworkConfig, epInfo *network.EndpointInfo, options map[string]interface{}) error + Delete(address *net.IPNet, nwCfg *cni.NetworkConfig, args *cniSkel.CmdArgs, options map[string]interface{}) error } diff --git a/cni/network/invoker_azure.go b/cni/network/invoker_azure.go index bb3c99361c..d8abfb067a 100644 --- a/cni/network/invoker_azure.go +++ b/cni/network/invoker_azure.go @@ -9,6 +9,7 @@ import ( "github.com/Azure/azure-container-networking/common" "github.com/Azure/azure-container-networking/log" "github.com/Azure/azure-container-networking/network" + cniSkel "github.com/containernetworking/cni/pkg/skel" cniTypesCurr "github.com/containernetworking/cni/pkg/types/current" ) @@ -24,7 +25,7 @@ func NewAzureIpamInvoker(plugin *netPlugin, nwInfo *network.NetworkInfo) *AzureI } } -func (invoker *AzureIPAMInvoker) Add(nwCfg *cni.NetworkConfig, subnetPrefix *net.IPNet, options map[string]interface{}) (*cniTypesCurr.Result, *cniTypesCurr.Result, error) { +func (invoker *AzureIPAMInvoker) Add(nwCfg *cni.NetworkConfig, _ *cniSkel.CmdArgs, subnetPrefix *net.IPNet, options map[string]interface{}) (*cniTypesCurr.Result, *cniTypesCurr.Result, error) { var ( result *cniTypesCurr.Result resultV6 *cniTypesCurr.Result @@ -79,7 +80,7 @@ func (invoker *AzureIPAMInvoker) Add(nwCfg *cni.NetworkConfig, subnetPrefix *net return result, resultV6, err } -func (invoker *AzureIPAMInvoker) Delete(address *net.IPNet, nwCfg *cni.NetworkConfig, _ *network.EndpointInfo, options map[string]interface{}) error { +func (invoker *AzureIPAMInvoker) Delete(address *net.IPNet, nwCfg *cni.NetworkConfig, _ *cniSkel.CmdArgs, options map[string]interface{}) error { if nwCfg == nil { return invoker.plugin.Errorf("nil nwCfg passed to CNI ADD, stack: %+v", string(debug.Stack())) diff --git a/cni/network/invoker_cns.go b/cni/network/invoker_cns.go index 89a173cde4..a93f6b0547 100644 --- a/cni/network/invoker_cns.go +++ b/cni/network/invoker_cns.go @@ -12,6 +12,7 @@ import ( "github.com/Azure/azure-container-networking/iptables" "github.com/Azure/azure-container-networking/log" "github.com/Azure/azure-container-networking/network" + cniSkel "github.com/containernetworking/cni/pkg/skel" cniTypes "github.com/containernetworking/cni/pkg/types" cniTypesCurr "github.com/containernetworking/cni/pkg/types/current" ) @@ -48,7 +49,7 @@ func NewCNSInvoker(podName, namespace string) (*CNSIPAMInvoker, error) { } //Add uses the requestipconfig API in cns, and returns ipv4 and a nil ipv6 as CNS doesn't support IPv6 yet -func (invoker *CNSIPAMInvoker) Add(nwCfg *cni.NetworkConfig, hostSubnetPrefix *net.IPNet, options map[string]interface{}) (*cniTypesCurr.Result, *cniTypesCurr.Result, error) { +func (invoker *CNSIPAMInvoker) Add(nwCfg *cni.NetworkConfig, args *cniSkel.CmdArgs, hostSubnetPrefix *net.IPNet, options map[string]interface{}) (*cniTypesCurr.Result, *cniTypesCurr.Result, error) { // Parse Pod arguments. podInfo := cns.KubernetesPodInfo{PodName: invoker.podName, PodNamespace: invoker.podNamespace} @@ -57,8 +58,12 @@ func (invoker *CNSIPAMInvoker) Add(nwCfg *cni.NetworkConfig, hostSubnetPrefix *n return nil, nil, err } + ipconfig := &cns.IPConfigRequest{ + OrchestratorContext: orchestratorContext, + } + log.Printf("Requesting IP for pod %v", podInfo) - response, err := invoker.cnsClient.RequestIPAddress(orchestratorContext) + response, err := invoker.cnsClient.RequestIPAddress(ipconfig) if err != nil { log.Printf("Failed to get IP address from CNS with error %v, response: %v", err, response) return nil, nil, err @@ -77,7 +82,7 @@ func (invoker *CNSIPAMInvoker) Add(nwCfg *cni.NetworkConfig, hostSubnetPrefix *n // set the NC Primary IP in options options[network.SNATIPKey] = info.ncPrimaryIP - log.Printf("[cni-invoker-cns] Received info %v for pod %v", info, podInfo) + log.Printf("[cni-invoker-cns] Received info %+v v for pod %v", info, podInfo) ncgw := net.ParseIP(info.ncGatewayIPAddress) if ncgw == nil { @@ -168,7 +173,7 @@ func setHostOptions(nwCfg *cni.NetworkConfig, hostSubnetPrefix *net.IPNet, ncSub } // Delete calls into the releaseipconfiguration API in CNS -func (invoker *CNSIPAMInvoker) Delete(address *net.IPNet, nwCfg *cni.NetworkConfig, epInfo *network.EndpointInfo, options map[string]interface{}) error { +func (invoker *CNSIPAMInvoker) Delete(address *net.IPNet, nwCfg *cni.NetworkConfig, args *cniSkel.CmdArgs, options map[string]interface{}) error { // Parse Pod arguments. podInfo := cns.KubernetesPodInfo{PodName: invoker.podName, PodNamespace: invoker.podNamespace} @@ -188,12 +193,12 @@ func (invoker *CNSIPAMInvoker) Delete(address *net.IPNet, nwCfg *cni.NetworkConf log.Printf("CNS invoker called with empty IP address") } - if epInfo != nil { - req.PodInterfaceID = epInfo.Id - req.InfraContainerID = epInfo.ContainerID - } else { - log.Printf("CNS invoker called with empty endpoint information") - } + // TODO: construct epinfo id if doesn't exist + + endpointId := GetEndpointID(args) + + req.PodInterfaceID = endpointId + req.InfraContainerID = args.ContainerID return invoker.cnsClient.ReleaseIPAddress(&req) } diff --git a/cni/network/network.go b/cni/network/network.go index 6a91f9913b..eafea5bde8 100644 --- a/cni/network/network.go +++ b/cni/network/network.go @@ -16,6 +16,7 @@ import ( "github.com/Azure/azure-container-networking/aitelemetry" "github.com/Azure/azure-container-networking/cni" + "github.com/Azure/azure-container-networking/cni/api" "github.com/Azure/azure-container-networking/cni/utils" "github.com/Azure/azure-container-networking/cns" "github.com/Azure/azure-container-networking/cns/cnsclient" @@ -154,6 +155,31 @@ func (plugin *netPlugin) Start(config *common.PluginConfig) error { return nil } +func (plugin *netPlugin) GetSimpleState() (*api.AzureCNIState, error) { + + st := api.AzureCNIState{ + ContainerInterfaces: make(map[string]api.NetworkInterfaceInfo), + } + + eps, err := plugin.nm.GetAllEndpoints("azure") + if err != nil { + return nil, err + } + + for _, ep := range eps { + id := ep.Id + info := api.NetworkInterfaceInfo{ + PodInterfaceID: ep.Id, + ContainerID: ep.ContainerID, + IPAddresses: ep.IPAddresses, + } + + st.ContainerInterfaces[id] = info + } + + return &st, err +} + // Stops the plugin. func (plugin *netPlugin) Stop() { plugin.nm.Uninitialize() @@ -474,7 +500,7 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error { log.Printf("[cni-net] Creating network %v.", networkId) if !nwCfg.MultiTenancy { - result, resultV6, err = plugin.ipamInvoker.Add(nwCfg, &subnetPrefix, options) + result, resultV6, err = plugin.ipamInvoker.Add(nwCfg, args, &subnetPrefix, options) if err != nil { return err } @@ -482,10 +508,10 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error { defer func() { if err != nil { if result != nil && len(result.IPs) > 0 { - plugin.ipamInvoker.Delete(&result.IPs[0].Address, nwCfg, epInfo, options) + plugin.ipamInvoker.Delete(&result.IPs[0].Address, nwCfg, args, options) } if resultV6 != nil && len(resultV6.IPs) > 0 { - plugin.ipamInvoker.Delete(&resultV6.IPs[0].Address, nwCfg, epInfo, options) + plugin.ipamInvoker.Delete(&resultV6.IPs[0].Address, nwCfg, args, options) } } }() @@ -576,7 +602,7 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error { if !nwCfg.MultiTenancy { // Network already exists. log.Printf("[cni-net] Found network %v with subnet %v.", networkId, nwInfo.Subnets[0].Prefix.String()) - result, resultV6, err = plugin.ipamInvoker.Add(nwCfg, &subnetPrefix, nwInfo.Options) + result, resultV6, err = plugin.ipamInvoker.Add(nwCfg, args, &subnetPrefix, nwInfo.Options) if err != nil { return err } @@ -586,10 +612,10 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error { defer func() { if err != nil { if result != nil && len(result.IPs) > 0 { - plugin.ipamInvoker.Delete(&result.IPs[0].Address, nwCfg, epInfo, nwInfo.Options) + plugin.ipamInvoker.Delete(&result.IPs[0].Address, nwCfg, args, nwInfo.Options) } if resultV6 != nil && len(resultV6.IPs) > 0 { - plugin.ipamInvoker.Delete(&resultV6.IPs[0].Address, nwCfg, epInfo, nwInfo.Options) + plugin.ipamInvoker.Delete(&resultV6.IPs[0].Address, nwCfg, args, nwInfo.Options) } } }() @@ -889,7 +915,7 @@ func (plugin *netPlugin) Delete(args *cniSkel.CmdArgs) error { if !nwCfg.MultiTenancy { // attempt to release address associated with this Endpoint id // This is to ensure clean up is done even in failure cases - err = plugin.ipamInvoker.Delete(nil, nwCfg, epInfo, nwInfo.Options) + err = plugin.ipamInvoker.Delete(nil, nwCfg, args, nwInfo.Options) if err != nil { log.Printf("Network not found, attempted to release address with error: %v", err) } @@ -908,7 +934,7 @@ func (plugin *netPlugin) Delete(args *cniSkel.CmdArgs) error { // attempt to release address associated with this Endpoint id // This is to ensure clean up is done even in failure cases log.Printf("release ip ep not found") - if err = plugin.ipamInvoker.Delete(nil, nwCfg, epInfo, nwInfo.Options); err != nil { + if err = plugin.ipamInvoker.Delete(nil, nwCfg, args, nwInfo.Options); err != nil { log.Printf("Endpoint not found, attempted to release address with error: %v", err) } } @@ -931,7 +957,7 @@ func (plugin *netPlugin) Delete(args *cniSkel.CmdArgs) error { // Call into IPAM plugin to release the endpoint's addresses. for _, address := range epInfo.IPAddresses { log.Printf("release ip:%s", address.IP.String()) - err = plugin.ipamInvoker.Delete(&address, nwCfg, epInfo, nwInfo.Options) + err = plugin.ipamInvoker.Delete(&address, nwCfg, args, nwInfo.Options) if err != nil { err = plugin.Errorf("Failed to release address %v with error: %v", address, err) return err @@ -940,7 +966,7 @@ func (plugin *netPlugin) Delete(args *cniSkel.CmdArgs) error { } else if epInfo.EnableInfraVnet { nwCfg.Ipam.Subnet = nwInfo.Subnets[0].Prefix.String() nwCfg.Ipam.Address = epInfo.InfraVnetIP.IP.String() - err = plugin.ipamInvoker.Delete(nil, nwCfg, epInfo, nwInfo.Options) + err = plugin.ipamInvoker.Delete(nil, nwCfg, args, nwInfo.Options) if err != nil { log.Printf("Failed to release address: %v", err) err = plugin.Errorf("Failed to release address %v with error: %v", nwCfg.Ipam.Address, err) diff --git a/cni/network/network_test.go b/cni/network/network_test.go index d58a6db03f..fe019d752b 100644 --- a/cni/network/network_test.go +++ b/cni/network/network_test.go @@ -6,26 +6,31 @@ import ( "testing" "github.com/Azure/azure-container-networking/cni" + "github.com/Azure/azure-container-networking/cni/api" "github.com/Azure/azure-container-networking/common" "github.com/Azure/azure-container-networking/network" acnnetwork "github.com/Azure/azure-container-networking/network" "github.com/Azure/azure-container-networking/nns" "github.com/Azure/azure-container-networking/telemetry" cniSkel "github.com/containernetworking/cni/pkg/skel" + "github.com/stretchr/testify/require" ) -// the Add/Delete methods in Plugin require refactoring to have UT's written for them, -// but the mocks in this test are a start -func TestPlugin(t *testing.T) { - config := &common.PluginConfig{} +func getTestResources() (*netPlugin, *acnnetwork.MockNetworkManager) { pluginName := "testplugin" - - mockNetworkManager := acnnetwork.NewMockNetworkmanager() - + config := &common.PluginConfig{} grpcClient := &nns.MockGrpcClient{} plugin, _ := NewPlugin(pluginName, config, grpcClient) plugin.report = &telemetry.CNIReport{} + mockNetworkManager := acnnetwork.NewMockNetworkmanager() plugin.nm = mockNetworkManager + return plugin, mockNetworkManager +} + +// the Add/Delete methods in Plugin require refactoring to have UT's written for them, +// but the mocks in this test are a start +func TestPlugin(t *testing.T) { + plugin, _ := getTestResources() nwCfg := cni.NetworkConfig{ Name: "test-nwcfg", @@ -71,3 +76,49 @@ func TestPlugin(t *testing.T) { plugin.nm.CreateNetwork(nwInfo) plugin.Delete(args) } + +func getTestEndpoint(ipwithcidr, podinterfaceid, infracontainerid string) *acnnetwork.EndpointInfo { + ip, ipnet, _ := net.ParseCIDR(ipwithcidr) + ipnet.IP = ip + ep := acnnetwork.EndpointInfo{ + Id: podinterfaceid, + ContainerID: infracontainerid, + IPAddresses: []net.IPNet{ + *ipnet, + }, + } + + return &ep +} + +func TestGetSimpleState(t *testing.T) { + + plugin, mockNetworkManager := getTestResources() + networkid := "azure" + + ep1 := getTestEndpoint("10.0.0.1/24", "podinterfaceid1", "testcontainerid1") + ep2 := getTestEndpoint("10.0.0.2/24", "podinterfaceid2", "testcontainerid2") + + mockNetworkManager.CreateEndpoint(networkid, ep1) + mockNetworkManager.CreateEndpoint(networkid, ep2) + + state, err := plugin.GetSimpleState() + require.NoError(t, err) + + res := &api.AzureCNIState{ + ContainerInterfaces: map[string]api.NetworkInterfaceInfo{ + ep1.Id: { + PodInterfaceID: ep1.Id, + ContainerID: ep1.ContainerID, + IPAddresses: ep1.IPAddresses, + }, + ep2.Id: { + PodInterfaceID: ep2.Id, + ContainerID: ep2.ContainerID, + IPAddresses: ep2.IPAddresses, + }, + }, + } + + require.Exactly(t, res, state) +} diff --git a/cni/network/plugin/main.go b/cni/network/plugin/main.go index 7f9abdee15..51f06e4b6d 100644 --- a/cni/network/plugin/main.go +++ b/cni/network/plugin/main.go @@ -6,12 +6,13 @@ package main import ( "encoding/json" "fmt" - "github.com/Azure/azure-container-networking/nns" "io/ioutil" "os" "reflect" "time" + "github.com/Azure/azure-container-networking/nns" + "github.com/Azure/azure-container-networking/cni" "github.com/Azure/azure-container-networking/cni/network" "github.com/Azure/azure-container-networking/common" @@ -230,6 +231,11 @@ func main() { cniCmd := os.Getenv(cni.Cmd) log.Printf("CNI_COMMAND environment variable set to %s", cniCmd) + // used to dump state + if cniCmd == cni.CmdState { + netPlugin.GetSimpleState() + } + handled, err := handleIfCniUpdate(netPlugin.Update) if handled == true { log.Printf("CNI UPDATE finished.") diff --git a/cns/cnsclient/cnsclient.go b/cns/cnsclient/cnsclient.go index e59c6c6a4e..1e303ae44b 100644 --- a/cns/cnsclient/cnsclient.go +++ b/cns/cnsclient/cnsclient.go @@ -211,7 +211,7 @@ func (cnsClient *CNSClient) DeleteHostNCApipaEndpoint(networkContainerID string) } // RequestIPAddress calls the requestIPAddress in CNS -func (cnsClient *CNSClient) RequestIPAddress(orchestratorContext []byte) (*cns.IPConfigResponse, error) { +func (cnsClient *CNSClient) RequestIPAddress(ipconfig *cns.IPConfigRequest) (*cns.IPConfigResponse, error) { var ( err error res *http.Response @@ -222,17 +222,13 @@ func (cnsClient *CNSClient) RequestIPAddress(orchestratorContext []byte) (*cns.I url := cnsClient.connectionURL + cns.RequestIPConfig - payload := &cns.IPConfigRequest{ - OrchestratorContext: orchestratorContext, - } - defer func() { if err != nil { - cnsClient.ReleaseIPAddress(payload) + cnsClient.ReleaseIPAddress(ipconfig) } }() - err = json.NewEncoder(&body).Encode(payload) + err = json.NewEncoder(&body).Encode(ipconfig) if err != nil { log.Errorf("encoding json failed with %v", err) return response, err diff --git a/network/endpoint_linux.go b/network/endpoint_linux.go index 25e34d04f0..0891e35bc8 100644 --- a/network/endpoint_linux.go +++ b/network/endpoint_linux.go @@ -31,7 +31,7 @@ func generateVethName(key string) string { return hex.EncodeToString(h.Sum(nil))[:11] } -func ConstructEndpointID(containerID string, netNsPath string, ifName string) (string, string) { +func ConstructEndpointID(containerID string, _ string, ifName string) (string, string) { if len(containerID) > 8 { containerID = containerID[:8] } else { diff --git a/network/manager.go b/network/manager.go index 42d3f4ed69..221953d430 100644 --- a/network/manager.go +++ b/network/manager.go @@ -72,6 +72,7 @@ type NetworkManager interface { CreateEndpoint(networkId string, epInfo *EndpointInfo) error DeleteEndpoint(networkId string, endpointId string) error GetEndpointInfo(networkId string, endpointId string) (*EndpointInfo, error) + GetAllEndpoints(networkId string) (map[string]*EndpointInfo, error) GetEndpointInfoBasedOnPODDetails(networkId string, podName string, podNameSpace string, doExactMatchForPodName bool) (*EndpointInfo, error) AttachEndpoint(networkId string, endpointId string, sandboxKey string) (*endpoint, error) DetachEndpoint(networkId string, endpointId string) error @@ -379,6 +380,24 @@ func (nm *networkManager) GetEndpointInfo(networkId string, endpointId string) ( return ep.getInfo(), nil } +func (nm *networkManager) GetAllEndpoints(networkId string) (map[string]*EndpointInfo, error) { + nm.Lock() + defer nm.Unlock() + + nw, err := nm.getNetwork(networkId) + if err != nil { + return nil, err + } + + eps := make(map[string]*EndpointInfo) + + for epid, ep := range nw.Endpoints { + eps[epid] = ep.getInfo() + } + + return eps, nil +} + // GetEndpointInfoBasedOnPODDetails returns information about the given endpoint. // It returns an error if a single pod has multiple endpoints. func (nm *networkManager) GetEndpointInfoBasedOnPODDetails(networkID string, podName string, podNameSpace string, doExactMatchForPodName bool) (*EndpointInfo, error) { diff --git a/network/manager_mock.go b/network/manager_mock.go index e097ad4968..6d49722591 100644 --- a/network/manager_mock.go +++ b/network/manager_mock.go @@ -9,15 +9,15 @@ import ( //MockNetworkManager is a mock structure for Network Manager type MockNetworkManager struct { - NetworkInfo map[string]*NetworkInfo - EndpointInfo map[string]*EndpointInfo + TestNetworkInfoMap map[string]*NetworkInfo + TestEndpointInfoMap map[string]*EndpointInfo } //NewMockNetworkmanager returns a new mock func NewMockNetworkmanager() *MockNetworkManager { return &MockNetworkManager{ - NetworkInfo: make(map[string]*NetworkInfo), - EndpointInfo: make(map[string]*EndpointInfo), + TestNetworkInfoMap: make(map[string]*NetworkInfo), + TestEndpointInfoMap: make(map[string]*EndpointInfo), } } @@ -36,7 +36,7 @@ func (nm *MockNetworkManager) AddExternalInterface(ifName string, subnet string) //CreateNetwork mock func (nm *MockNetworkManager) CreateNetwork(nwInfo *NetworkInfo) error { - nm.NetworkInfo[nwInfo.Id] = nwInfo + nm.TestNetworkInfoMap[nwInfo.Id] = nwInfo return nil } @@ -47,7 +47,7 @@ func (nm *MockNetworkManager) DeleteNetwork(networkID string) error { //GetNetworkInfo mock func (nm *MockNetworkManager) GetNetworkInfo(networkID string) (NetworkInfo, error) { - if info, exists := nm.NetworkInfo[networkID]; exists { + if info, exists := nm.TestNetworkInfoMap[networkID]; exists { return *info, nil } return NetworkInfo{}, fmt.Errorf("Not found") @@ -55,7 +55,7 @@ func (nm *MockNetworkManager) GetNetworkInfo(networkID string) (NetworkInfo, err //CreateEndpoint mock func (nm *MockNetworkManager) CreateEndpoint(networkID string, epInfo *EndpointInfo) error { - nm.EndpointInfo[networkID] = epInfo + nm.TestEndpointInfoMap[epInfo.Id] = epInfo return nil } @@ -64,9 +64,13 @@ func (nm *MockNetworkManager) DeleteEndpoint(networkID string, endpointID string return nil } +func (nm *MockNetworkManager) GetAllEndpoints(networkID string) (map[string]*EndpointInfo, error) { + return nm.TestEndpointInfoMap, nil +} + //GetEndpointInfo mock func (nm *MockNetworkManager) GetEndpointInfo(networkID string, endpointID string) (*EndpointInfo, error) { - return nm.EndpointInfo[networkID], nil + return nm.TestEndpointInfoMap[networkID], nil } //GetEndpointInfoBasedOnPODDetails mock diff --git a/network/network.go b/network/network.go index 50c4da7784..68b440dec8 100644 --- a/network/network.go +++ b/network/network.go @@ -25,7 +25,7 @@ const ( IPV6Nat = "ipv6nat" ) -// ExternalInterface is a host network interface that bridges containers to external networks. +// externalInterface is a host network interface that bridges containers to external networks. type externalInterface struct { Name string Networks map[string]*network From 984c5a5e06534e2ebc1b9d27b5d9a61b4abaae99 Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Fri, 4 Jun 2021 12:44:38 -0700 Subject: [PATCH 2/8] add reconcile command to CNI --- cni/api/api.go | 2 ++ cni/client/client.go | 43 ++++++++++++++++++++++++++++++++ cni/client/client_test.go | 49 +++++++++++++++++++++++++++++++++++++ cni/network/network_test.go | 4 ++- npm/ipsm/ipsm_test.go | 8 +++--- test/utils/utils.go | 10 ++++---- 6 files changed, 106 insertions(+), 10 deletions(-) create mode 100644 cni/client/client.go create mode 100644 cni/client/client_test.go diff --git a/cni/api/api.go b/cni/api/api.go index 937dcdcac4..5ea12a4abd 100644 --- a/cni/api/api.go +++ b/cni/api/api.go @@ -3,6 +3,8 @@ package api import "net" type NetworkInterfaceInfo struct { + PodName string // todo: populate these in cni + PodNamespace string PodInterfaceID string ContainerID string IPAddresses []net.IPNet diff --git a/cni/client/client.go b/cni/client/client.go new file mode 100644 index 0000000000..d1007d981b --- /dev/null +++ b/cni/client/client.go @@ -0,0 +1,43 @@ +package client + +import ( + "encoding/json" + "fmt" + "os" + + "github.com/Azure/azure-container-networking/cni" + "github.com/Azure/azure-container-networking/cni/api" + utilexec "k8s.io/utils/exec" +) + +type CNIClient struct { + exec utilexec.Interface +} + +func NewCNIClient(exec utilexec.Interface) *CNIClient { + return &CNIClient{ + exec: exec, + } +} + +func (c *CNIClient) GetState() (*api.AzureCNIState, error) { + cmd := c.exec.Command("./azure-vnet") + cmd.SetDir("/opt/cni/bin") + + envs := os.Environ() + envs = append(envs, fmt.Sprintf("%s=%s", cni.Cmd, cni.CmdState)) + + cmd.SetEnv(envs) + + output, err := cmd.CombinedOutput() + if err != nil { + return nil, err + } + + state := &api.AzureCNIState{} + if err := json.Unmarshal(output, state); err != nil { + return nil, fmt.Errorf("Failed to decode response from CNI when retrieving state: [%w], response from CNI: [%s]", err, string(output)) + } + + return state, nil +} diff --git a/cni/client/client_test.go b/cni/client/client_test.go new file mode 100644 index 0000000000..29399f1650 --- /dev/null +++ b/cni/client/client_test.go @@ -0,0 +1,49 @@ +package client + +import ( + "fmt" + "net" + "testing" + + "github.com/Azure/azure-container-networking/cni/api" + testutils "github.com/Azure/azure-container-networking/test/utils" + "github.com/stretchr/testify/require" + "k8s.io/utils/exec" +) + +func testGetNetworkInterfaceInfo(podinterfaceid, podname, podnamespace, containerid, ipwithcidr string) api.NetworkInterfaceInfo { + ip, ipnet, _ := net.ParseCIDR(ipwithcidr) + ipnet.IP = ip + return api.NetworkInterfaceInfo{ + PodName: podname, + PodNamespace: podnamespace, + PodInterfaceID: podinterfaceid, + ContainerID: containerid, + IPAddresses: []net.IPNet{ + *ipnet, + }, + } +} + +func TestGetState(t *testing.T) { + calls := []testutils.TestCmd{ + // not really stderr, going to change to stdout in #868 + {Cmd: []string{"./azure-vnet"}, Stdout: `{"ContainerInterfaces":{"podinterfaceid1":{"PodName":"podname1","PodNamespace":"podnamespace1","PodInterfaceID":"podinterfaceid1","ContainerID":"testcontainerid1","IPAddresses":[{"IP":"10.0.0.1","Mask":"////AA=="}]},"podinterfaceid2":{"PodName":"podname2","PodNamespace":"podnamespace2","PodInterfaceID":"podinterfaceid2","ContainerID":"testcontainerid2","IPAddresses":[{"IP":"10.0.0.2","Mask":"////AA=="}]}}}`}, + } + + //fakeexec, _ := testutils.GetFakeExecWithScripts(calls) + fmt.Print(calls) + fakeexec := exec.New() + c := NewCNIClient(fakeexec) + state, err := c.GetState() + require.NoError(t, err) + + res := &api.AzureCNIState{ + ContainerInterfaces: map[string]api.NetworkInterfaceInfo{ + "podinterfaceid1": testGetNetworkInterfaceInfo("podinterfaceid1", "podname1", "podnamespace1", "testcontainerid1", "10.0.0.1/24"), + "podinterfaceid2": testGetNetworkInterfaceInfo("podinterfaceid2", "podname2", "podnamespace2", "testcontainerid2", "10.0.0.2/24"), + }, + } + + require.Exactly(t, res, state) +} diff --git a/cni/network/network_test.go b/cni/network/network_test.go index fe019d752b..af3a14528a 100644 --- a/cni/network/network_test.go +++ b/cni/network/network_test.go @@ -1,6 +1,7 @@ package network import ( + "encoding/json" "fmt" "net" "testing" @@ -119,6 +120,7 @@ func TestGetSimpleState(t *testing.T) { }, }, } - + b, _ := json.Marshal(res) + require.FailNow(t, string(b)) require.Exactly(t, res, state) } diff --git a/npm/ipsm/ipsm_test.go b/npm/ipsm/ipsm_test.go index ec09c4b225..1cec012688 100644 --- a/npm/ipsm/ipsm_test.go +++ b/npm/ipsm/ipsm_test.go @@ -104,10 +104,10 @@ func TestDeleteFromList(t *testing.T) { {Cmd: []string{"ipset", "test", "-exist", util.GetHashedName("test-list"), util.GetHashedName("test-set")}}, {Cmd: []string{"ipset", "-D", "-exist", util.GetHashedName("test-list"), util.GetHashedName("test-set")}}, {Cmd: []string{"ipset", "-X", "-exist", util.GetHashedName("test-list")}}, - {Cmd: []string{"ipset", "test", "-exist", util.GetHashedName("test-list"), util.GetHashedName("test-set")}, Stderr: "ipset still exists", ExitCode: 2}, - {Cmd: []string{"ipset", "list", "-exist", util.GetHashedName("test-list")}, Stderr: "ipset still exists", ExitCode: 2}, + {Cmd: []string{"ipset", "test", "-exist", util.GetHashedName("test-list"), util.GetHashedName("test-set")}, Stdout: "ipset still exists", ExitCode: 2}, + {Cmd: []string{"ipset", "list", "-exist", util.GetHashedName("test-list")}, Stdout: "ipset still exists", ExitCode: 2}, {Cmd: []string{"ipset", "-X", "-exist", util.GetHashedName("test-set")}}, - {Cmd: []string{"ipset", "list", "-exist", util.GetHashedName("test-set")}, Stderr: "ipset still exists", ExitCode: 2}, + {Cmd: []string{"ipset", "list", "-exist", util.GetHashedName("test-set")}, Stdout: "ipset still exists", ExitCode: 2}, } fexec, fcmd := testutils.GetFakeExecWithScripts(calls) @@ -570,7 +570,7 @@ func TestRunError(t *testing.T) { setname := "test-set" var calls = []testutils.TestCmd{ - {Cmd: []string{"ipset", "-N", "-exist", util.GetHashedName(setname), "nethash"}, Stderr: "test failure", ExitCode: 2}, + {Cmd: []string{"ipset", "-N", "-exist", util.GetHashedName(setname), "nethash"}, Stdout: "test failure", ExitCode: 2}, } fexec, fcmd := testutils.GetFakeExecWithScripts(calls) diff --git a/test/utils/utils.go b/test/utils/utils.go index 0d33b491ea..ee8925ffe7 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -11,7 +11,7 @@ import ( type TestCmd struct { Cmd []string - Stderr string + Stdout string ExitCode int } @@ -21,12 +21,12 @@ func GetFakeExecWithScripts(calls []TestCmd) (*fakeexec.FakeExec, *fakeexec.Fake fcmd := &fakeexec.FakeCmd{} for _, call := range calls { - if call.Stderr != "" || call.ExitCode != 0 { - stderr := call.Stderr + stdout := call.Stdout + if call.ExitCode != 0 { err := &fakeexec.FakeExitError{Status: call.ExitCode} - fcmd.CombinedOutputScript = append(fcmd.CombinedOutputScript, func() ([]byte, []byte, error) { return []byte(stderr), nil, err }) + fcmd.CombinedOutputScript = append(fcmd.CombinedOutputScript, func() ([]byte, []byte, error) { return []byte(stdout), nil, err }) } else { - fcmd.CombinedOutputScript = append(fcmd.CombinedOutputScript, func() ([]byte, []byte, error) { return []byte{}, nil, nil }) + fcmd.CombinedOutputScript = append(fcmd.CombinedOutputScript, func() ([]byte, []byte, error) { return []byte(stdout), nil, nil }) } } From 364dc84771ed95dbe317573c940b33a4e9fda125 Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Fri, 4 Jun 2021 22:33:20 +0000 Subject: [PATCH 3/8] add integration test --- Makefile | 2 +- cni/client/client.go | 4 +- cni/client/client_common_test.go | 21 +++++++++ cni/client/client_integration_test.go | 63 +++++++++++++++++++++++++ cni/client/client_test.go | 49 -------------------- cni/client/client_unit_test.go | 32 +++++++++++++ cni/cni.go | 2 +- cni/network/network.go | 2 + cni/network/network_test.go | 23 +++++---- cni/network/plugin/main.go | 67 ++++++++++++++++----------- test/utils/utils.go | 27 +++++++++++ 11 files changed, 202 insertions(+), 90 deletions(-) create mode 100644 cni/client/client_common_test.go create mode 100644 cni/client/client_integration_test.go delete mode 100644 cni/client/client_test.go create mode 100644 cni/client/client_unit_test.go diff --git a/Makefile b/Makefile index c87533d682..6df11bf606 100644 --- a/Makefile +++ b/Makefile @@ -460,7 +460,7 @@ PRETTYGOTEST := $(shell command -v gotest 2> /dev/null) # run all tests .PHONY: test-all test-all: - go test -coverpkg=./... -v -race -covermode atomic -failfast -coverprofile=coverage.out ./... + go test -tags "unit integration" -coverpkg=./... -v -race -covermode atomic -failfast -coverprofile=coverage.out ./... # run all tests .PHONY: test-integration diff --git a/cni/client/client.go b/cni/client/client.go index d1007d981b..b9bd69aee1 100644 --- a/cni/client/client.go +++ b/cni/client/client.go @@ -31,12 +31,12 @@ func (c *CNIClient) GetState() (*api.AzureCNIState, error) { output, err := cmd.CombinedOutput() if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to call Azure CNI bin with err: [%w], output: [%s]", err, string(output)) } state := &api.AzureCNIState{} if err := json.Unmarshal(output, state); err != nil { - return nil, fmt.Errorf("Failed to decode response from CNI when retrieving state: [%w], response from CNI: [%s]", err, string(output)) + return nil, fmt.Errorf("Failed to decode response from Azure CNI when retrieving state: [%w], response from CNI: [%s]", err, string(output)) } return state, nil diff --git a/cni/client/client_common_test.go b/cni/client/client_common_test.go new file mode 100644 index 0000000000..0504a93a56 --- /dev/null +++ b/cni/client/client_common_test.go @@ -0,0 +1,21 @@ +package client + +import ( + "net" + + "github.com/Azure/azure-container-networking/cni/api" +) + +func testGetNetworkInterfaceInfo(podinterfaceid, podname, podnamespace, containerid, ipwithcidr string) api.NetworkInterfaceInfo { + ip, ipnet, _ := net.ParseCIDR(ipwithcidr) + ipnet.IP = ip + return api.NetworkInterfaceInfo{ + PodName: podname, + PodNamespace: podnamespace, + PodInterfaceID: podinterfaceid, + ContainerID: containerid, + IPAddresses: []net.IPNet{ + *ipnet, + }, + } +} diff --git a/cni/client/client_integration_test.go b/cni/client/client_integration_test.go new file mode 100644 index 0000000000..e501a3d30e --- /dev/null +++ b/cni/client/client_integration_test.go @@ -0,0 +1,63 @@ +// +build linux +// +build integration + +package client + +import ( + "io" + "log" + "os" + "os/user" + "testing" + + "github.com/Azure/azure-container-networking/cni/api" + testutils "github.com/Azure/azure-container-networking/test/utils" + "github.com/stretchr/testify/require" + "k8s.io/utils/exec" +) + +func isRoot() bool { + currentUser, err := user.Current() + if err != nil { + log.Fatalf("[isRoot] Unable to get current user: %s", err) + } + return currentUser.Username == "root" +} + +func TestGetStateFromAzureCNI(t *testing.T) { + testutils.RequireRootforTest(t) + + // copy test state file to /var/run/azure-vnet.json + in, err := os.Open("./azure-vnet-test.json") + require.NoError(t, err) + + defer in.Close() + + out, err := os.Create("/var/run/azure-vnet.json") + require.NoError(t, err) + + defer func() { + out.Close() + err := os.Remove("/var/run/azure-vnet.json") + require.NoError(t, err) + }() + + _, err = io.Copy(out, in) + require.NoError(t, err) + + out.Close() + + realexec := exec.New() + c := NewCNIClient(realexec) + state, err := c.GetState() + require.NoError(t, err) + + res := &api.AzureCNIState{ + ContainerInterfaces: map[string]api.NetworkInterfaceInfo{ + "3f813b02-eth0": testGetNetworkInterfaceInfo("3f813b02-eth0", "metrics-server-77c8679d7d-6ksdh", "kube-system", "3f813b029429b4e41a09ab33b6f6d365d2ed704017524c78d1d0dece33cdaf46", "10.241.0.17/16"), + "6e688597-eth0": testGetNetworkInterfaceInfo("6e688597-eth0", "tunnelfront-5d96f9b987-65xbn", "kube-system", "6e688597eafb97c83c84e402cc72b299bfb8aeb02021e4c99307a037352c0bed", "10.241.0.13/16"), + }, + } + + require.Exactly(t, res, state) +} diff --git a/cni/client/client_test.go b/cni/client/client_test.go deleted file mode 100644 index 29399f1650..0000000000 --- a/cni/client/client_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package client - -import ( - "fmt" - "net" - "testing" - - "github.com/Azure/azure-container-networking/cni/api" - testutils "github.com/Azure/azure-container-networking/test/utils" - "github.com/stretchr/testify/require" - "k8s.io/utils/exec" -) - -func testGetNetworkInterfaceInfo(podinterfaceid, podname, podnamespace, containerid, ipwithcidr string) api.NetworkInterfaceInfo { - ip, ipnet, _ := net.ParseCIDR(ipwithcidr) - ipnet.IP = ip - return api.NetworkInterfaceInfo{ - PodName: podname, - PodNamespace: podnamespace, - PodInterfaceID: podinterfaceid, - ContainerID: containerid, - IPAddresses: []net.IPNet{ - *ipnet, - }, - } -} - -func TestGetState(t *testing.T) { - calls := []testutils.TestCmd{ - // not really stderr, going to change to stdout in #868 - {Cmd: []string{"./azure-vnet"}, Stdout: `{"ContainerInterfaces":{"podinterfaceid1":{"PodName":"podname1","PodNamespace":"podnamespace1","PodInterfaceID":"podinterfaceid1","ContainerID":"testcontainerid1","IPAddresses":[{"IP":"10.0.0.1","Mask":"////AA=="}]},"podinterfaceid2":{"PodName":"podname2","PodNamespace":"podnamespace2","PodInterfaceID":"podinterfaceid2","ContainerID":"testcontainerid2","IPAddresses":[{"IP":"10.0.0.2","Mask":"////AA=="}]}}}`}, - } - - //fakeexec, _ := testutils.GetFakeExecWithScripts(calls) - fmt.Print(calls) - fakeexec := exec.New() - c := NewCNIClient(fakeexec) - state, err := c.GetState() - require.NoError(t, err) - - res := &api.AzureCNIState{ - ContainerInterfaces: map[string]api.NetworkInterfaceInfo{ - "podinterfaceid1": testGetNetworkInterfaceInfo("podinterfaceid1", "podname1", "podnamespace1", "testcontainerid1", "10.0.0.1/24"), - "podinterfaceid2": testGetNetworkInterfaceInfo("podinterfaceid2", "podname2", "podnamespace2", "testcontainerid2", "10.0.0.2/24"), - }, - } - - require.Exactly(t, res, state) -} diff --git a/cni/client/client_unit_test.go b/cni/client/client_unit_test.go new file mode 100644 index 0000000000..94c47da9a2 --- /dev/null +++ b/cni/client/client_unit_test.go @@ -0,0 +1,32 @@ +// +build unit + +package client + +import ( + "testing" + + "github.com/Azure/azure-container-networking/cni/api" + testutils "github.com/Azure/azure-container-networking/test/utils" + "github.com/stretchr/testify/require" +) + +func TestGetState(t *testing.T) { + calls := []testutils.TestCmd{ + {Cmd: []string{"./azure-vnet"}, Stdout: `{"ContainerInterfaces":{"3f813b02-eth0":{"PodName":"metrics-server-77c8679d7d-6ksdh","PodNamespace":"kube-system","PodInterfaceID":"3f813b02-eth0","ContainerID":"3f813b029429b4e41a09ab33b6f6d365d2ed704017524c78d1d0dece33cdaf46","IPAddresses":[{"IP":"10.241.0.17","Mask":"//8AAA=="}]},"6e688597-eth0":{"PodName":"tunnelfront-5d96f9b987-65xbn","PodNamespace":"kube-system","PodInterfaceID":"6e688597-eth0","ContainerID":"6e688597eafb97c83c84e402cc72b299bfb8aeb02021e4c99307a037352c0bed","IPAddresses":[{"IP":"10.241.0.13","Mask":"//8AAA=="}]}}}`}, + } + + fakeexec, _ := testutils.GetFakeExecWithScripts(calls) + + c := NewCNIClient(fakeexec) + state, err := c.GetState() + require.NoError(t, err) + + res := &api.AzureCNIState{ + ContainerInterfaces: map[string]api.NetworkInterfaceInfo{ + "3f813b02-eth0": testGetNetworkInterfaceInfo("3f813b02-eth0", "metrics-server-77c8679d7d-6ksdh", "kube-system", "3f813b029429b4e41a09ab33b6f6d365d2ed704017524c78d1d0dece33cdaf46", "10.241.0.17/16"), + "6e688597-eth0": testGetNetworkInterfaceInfo("6e688597-eth0", "tunnelfront-5d96f9b987-65xbn", "kube-system", "6e688597eafb97c83c84e402cc72b299bfb8aeb02021e4c99307a037352c0bed", "10.241.0.13/16"), + }, + } + + require.Exactly(t, res, state) +} diff --git a/cni/cni.go b/cni/cni.go index 4738b3be8a..12bced5596 100644 --- a/cni/cni.go +++ b/cni/cni.go @@ -16,7 +16,7 @@ const ( CmdUpdate = "UPDATE" // nonstandard CNI spec command, used to dump CNI state to stdout - CmdState = "STATE" + CmdState = "GET_STATE" // CNI errors. ErrRuntime = 100 diff --git a/cni/network/network.go b/cni/network/network.go index eafea5bde8..217ad888e2 100644 --- a/cni/network/network.go +++ b/cni/network/network.go @@ -169,6 +169,8 @@ func (plugin *netPlugin) GetSimpleState() (*api.AzureCNIState, error) { for _, ep := range eps { id := ep.Id info := api.NetworkInterfaceInfo{ + PodName: ep.PODName, + PodNamespace: ep.PODNameSpace, PodInterfaceID: ep.Id, ContainerID: ep.ContainerID, IPAddresses: ep.IPAddresses, diff --git a/cni/network/network_test.go b/cni/network/network_test.go index af3a14528a..58dc87b388 100644 --- a/cni/network/network_test.go +++ b/cni/network/network_test.go @@ -1,7 +1,6 @@ package network import ( - "encoding/json" "fmt" "net" "testing" @@ -75,15 +74,17 @@ func TestPlugin(t *testing.T) { Options: make(map[string]interface{}), } plugin.nm.CreateNetwork(nwInfo) - plugin.Delete(args) + // plugin.Delete(args) } -func getTestEndpoint(ipwithcidr, podinterfaceid, infracontainerid string) *acnnetwork.EndpointInfo { +func getTestEndpoint(podname, podnamespace, ipwithcidr, podinterfaceid, infracontainerid string) *acnnetwork.EndpointInfo { ip, ipnet, _ := net.ParseCIDR(ipwithcidr) ipnet.IP = ip ep := acnnetwork.EndpointInfo{ - Id: podinterfaceid, - ContainerID: infracontainerid, + PODName: podname, + PODNameSpace: podnamespace, + Id: podinterfaceid, + ContainerID: infracontainerid, IPAddresses: []net.IPNet{ *ipnet, }, @@ -93,12 +94,11 @@ func getTestEndpoint(ipwithcidr, podinterfaceid, infracontainerid string) *acnne } func TestGetSimpleState(t *testing.T) { - plugin, mockNetworkManager := getTestResources() networkid := "azure" - ep1 := getTestEndpoint("10.0.0.1/24", "podinterfaceid1", "testcontainerid1") - ep2 := getTestEndpoint("10.0.0.2/24", "podinterfaceid2", "testcontainerid2") + ep1 := getTestEndpoint("podname1", "podnamespace1", "10.0.0.1/24", "podinterfaceid1", "testcontainerid1") + ep2 := getTestEndpoint("podname2", "podnamespace2", "10.0.0.2/24", "podinterfaceid2", "testcontainerid2") mockNetworkManager.CreateEndpoint(networkid, ep1) mockNetworkManager.CreateEndpoint(networkid, ep2) @@ -110,17 +110,20 @@ func TestGetSimpleState(t *testing.T) { ContainerInterfaces: map[string]api.NetworkInterfaceInfo{ ep1.Id: { PodInterfaceID: ep1.Id, + PodName: ep1.PODName, + PodNamespace: ep1.PODNameSpace, ContainerID: ep1.ContainerID, IPAddresses: ep1.IPAddresses, }, ep2.Id: { PodInterfaceID: ep2.Id, + PodName: ep2.PODName, + PodNamespace: ep2.PODNameSpace, ContainerID: ep2.ContainerID, IPAddresses: ep2.IPAddresses, }, }, } - b, _ := json.Marshal(res) - require.FailNow(t, string(b)) + require.Exactly(t, res, state) } diff --git a/cni/network/plugin/main.go b/cni/network/plugin/main.go index 51f06e4b6d..49cadb6245 100644 --- a/cni/network/plugin/main.go +++ b/cni/network/plugin/main.go @@ -227,13 +227,52 @@ func main() { panic("network plugin start fatal error") } + defer func() { + netPlugin.Stop() + + // release cni lock + if errUninit := netPlugin.Plugin.UninitializeKeyValueStore(false); errUninit != nil { + log.Errorf("Failed to uninitialize key-value store of network plugin, err:%v.\n", errUninit) + } + + executionTimeMs := time.Since(startTime).Milliseconds() + + if err != nil { + reportPluginError(reportManager, tb, err) + panic("network plugin execute fatal error") + } + + // Report CNI successfully finished execution. + reflect.ValueOf(reportManager.Report).Elem().FieldByName("CniSucceeded").SetBool(true) + reflect.ValueOf(reportManager.Report).Elem().FieldByName("OperationDuration").SetInt(executionTimeMs) + + if cniReport.ErrorMessage != "" || cniReport.EventMessage != "" { + if err = reportManager.SendReport(tb); err != nil { + log.Errorf("SendReport failed due to %v", err) + } else { + log.Printf("Sending report succeeded") + } + } + }() + // Check CNI_COMMAND value for logging purposes. cniCmd := os.Getenv(cni.Cmd) log.Printf("CNI_COMMAND environment variable set to %s", cniCmd) // used to dump state if cniCmd == cni.CmdState { - netPlugin.GetSimpleState() + log.Printf("Retrieving state") + simpleState, err := netPlugin.GetSimpleState() + if err != nil { + log.Errorf("Failed to get Azure CNI state, err:%v.\n", err) + } + b, err := json.Marshal(simpleState) + if err != nil { + log.Errorf("Failed to unmarshall Azure CNI state, err:%v.\n", err) + } + log.Printf("State: %s", string(b)) + fmt.Printf("%s\n", string(b)) + return } handled, err := handleIfCniUpdate(netPlugin.Update) @@ -242,30 +281,4 @@ func main() { } else if err = netPlugin.Execute(cni.PluginApi(netPlugin)); err != nil { log.Errorf("Failed to execute network plugin, err:%v.\n", err) } - - netPlugin.Stop() - - // release cni lock - if errUninit := netPlugin.Plugin.UninitializeKeyValueStore(false); errUninit != nil { - log.Errorf("Failed to uninitialize key-value store of network plugin, err:%v.\n", errUninit) - } - - executionTimeMs := time.Since(startTime).Milliseconds() - - if err != nil { - reportPluginError(reportManager, tb, err) - panic("network plugin execute fatal error") - } - - // Report CNI successfully finished execution. - reflect.ValueOf(reportManager.Report).Elem().FieldByName("CniSucceeded").SetBool(true) - reflect.ValueOf(reportManager.Report).Elem().FieldByName("OperationDuration").SetInt(executionTimeMs) - - if cniReport.ErrorMessage != "" || cniReport.EventMessage != "" { - if err = reportManager.SendReport(tb); err != nil { - log.Errorf("SendReport failed due to %v", err) - } else { - log.Printf("Sending report succeeded") - } - } } diff --git a/test/utils/utils.go b/test/utils/utils.go index ee8925ffe7..e9b8295aa5 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -1,6 +1,9 @@ package testingutils import ( + "log" + "os" + "os/user" "testing" "github.com/stretchr/testify/require" @@ -44,3 +47,27 @@ func VerifyCallsMatch(t *testing.T, calls []TestCmd, fexec *fakeexec.FakeExec, f require.Equalf(t, call.Cmd, fcmd.CombinedOutputLog[i], "Call [%d] doesn't match expected", i) } } + +func isRoot() bool { + currentUser, err := user.Current() + if err != nil { + log.Printf("Failed to get current user") + return false + } else if currentUser.Username == "root" { + return true + } + return false +} + +func RequireRootforTest(t *testing.T) { + if !isRoot() { + t.Fatalf("Test [%s] requires root!", t.Name()) + } +} + +func RequireRootforTestMain(m *testing.M) { + if !isRoot() { + log.Printf("These tests require root!") + os.Exit(1) + } +} From a01039a3125cf2e849228c01136b2e74e15d72a2 Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Fri, 4 Jun 2021 22:57:54 +0000 Subject: [PATCH 4/8] pass endpoint id on add --- cni/api/api.go | 2 +- cni/client/client.go | 1 - cni/client/client_common_test.go | 2 ++ cni/network/invoker_azure.go | 4 +++- cni/network/invoker_cns.go | 17 ++++++++--------- cni/network/network.go | 17 ++++++++++++----- cni/network/network_test.go | 7 +++++-- 7 files changed, 31 insertions(+), 19 deletions(-) diff --git a/cni/api/api.go b/cni/api/api.go index 5ea12a4abd..94bb80ba7f 100644 --- a/cni/api/api.go +++ b/cni/api/api.go @@ -3,7 +3,7 @@ package api import "net" type NetworkInterfaceInfo struct { - PodName string // todo: populate these in cni + PodName string PodNamespace string PodInterfaceID string ContainerID string diff --git a/cni/client/client.go b/cni/client/client.go index b9bd69aee1..a041ce12c5 100644 --- a/cni/client/client.go +++ b/cni/client/client.go @@ -26,7 +26,6 @@ func (c *CNIClient) GetState() (*api.AzureCNIState, error) { envs := os.Environ() envs = append(envs, fmt.Sprintf("%s=%s", cni.Cmd, cni.CmdState)) - cmd.SetEnv(envs) output, err := cmd.CombinedOutput() diff --git a/cni/client/client_common_test.go b/cni/client/client_common_test.go index 0504a93a56..18063ee7f6 100644 --- a/cni/client/client_common_test.go +++ b/cni/client/client_common_test.go @@ -1,3 +1,5 @@ +// +build unit integration + package client import ( diff --git a/cni/network/invoker_azure.go b/cni/network/invoker_azure.go index d8abfb067a..ee3d821d06 100644 --- a/cni/network/invoker_azure.go +++ b/cni/network/invoker_azure.go @@ -51,7 +51,9 @@ func (invoker *AzureIPAMInvoker) Add(nwCfg *cni.NetworkConfig, _ *cniSkel.CmdArg defer func() { if err != nil { if len(result.IPs) > 0 { - invoker.plugin.ipamInvoker.Delete(&result.IPs[0].Address, nwCfg, nil, options) + if er := invoker.plugin.ipamInvoker.Delete(&result.IPs[0].Address, nwCfg, nil, options); er != nil { + err = invoker.plugin.Errorf("Failed to clean up IP's during Delete with error %v, after Add failed with error %w", er, err) + } } else { err = fmt.Errorf("No IP's to delete on error: %v", err) } diff --git a/cni/network/invoker_cns.go b/cni/network/invoker_cns.go index a93f6b0547..13c2f26134 100644 --- a/cni/network/invoker_cns.go +++ b/cni/network/invoker_cns.go @@ -58,12 +58,15 @@ func (invoker *CNSIPAMInvoker) Add(nwCfg *cni.NetworkConfig, args *cniSkel.CmdAr return nil, nil, err } - ipconfig := &cns.IPConfigRequest{ + endpointId := GetEndpointID(args) + ipconfig := cns.IPConfigRequest{ OrchestratorContext: orchestratorContext, + PodInterfaceID: endpointId, + InfraContainerID: args.ContainerID, } log.Printf("Requesting IP for pod %v", podInfo) - response, err := invoker.cnsClient.RequestIPAddress(ipconfig) + response, err := invoker.cnsClient.RequestIPAddress(&ipconfig) if err != nil { log.Printf("Failed to get IP address from CNS with error %v, response: %v", err, response) return nil, nil, err @@ -183,8 +186,11 @@ func (invoker *CNSIPAMInvoker) Delete(address *net.IPNet, nwCfg *cni.NetworkConf return err } + endpointId := GetEndpointID(args) req := cns.IPConfigRequest{ OrchestratorContext: orchestratorContext, + PodInterfaceID: endpointId, + InfraContainerID: args.ContainerID, } if address != nil { @@ -193,12 +199,5 @@ func (invoker *CNSIPAMInvoker) Delete(address *net.IPNet, nwCfg *cni.NetworkConf log.Printf("CNS invoker called with empty IP address") } - // TODO: construct epinfo id if doesn't exist - - endpointId := GetEndpointID(args) - - req.PodInterfaceID = endpointId - req.InfraContainerID = args.ContainerID - return invoker.cnsClient.ReleaseIPAddress(&req) } diff --git a/cni/network/network.go b/cni/network/network.go index 217ad888e2..b418935ba5 100644 --- a/cni/network/network.go +++ b/cni/network/network.go @@ -156,7 +156,6 @@ func (plugin *netPlugin) Start(config *common.PluginConfig) error { } func (plugin *netPlugin) GetSimpleState() (*api.AzureCNIState, error) { - st := api.AzureCNIState{ ContainerInterfaces: make(map[string]api.NetworkInterfaceInfo), } @@ -510,10 +509,14 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error { defer func() { if err != nil { if result != nil && len(result.IPs) > 0 { - plugin.ipamInvoker.Delete(&result.IPs[0].Address, nwCfg, args, options) + if er := plugin.ipamInvoker.Delete(&result.IPs[0].Address, nwCfg, args, options); er != nil { + err = plugin.Errorf("Failed to cleanup when NwInfo was not nil with error %v, after Add failed with error %w", er, err) + } } if resultV6 != nil && len(resultV6.IPs) > 0 { - plugin.ipamInvoker.Delete(&resultV6.IPs[0].Address, nwCfg, args, options) + if er := plugin.ipamInvoker.Delete(&resultV6.IPs[0].Address, nwCfg, args, options); er != nil { + err = plugin.Errorf("Failed to cleanup when NwInfo was not nil with error %v, after Add failed with error %w", er, err) + } } } }() @@ -614,10 +617,14 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error { defer func() { if err != nil { if result != nil && len(result.IPs) > 0 { - plugin.ipamInvoker.Delete(&result.IPs[0].Address, nwCfg, args, nwInfo.Options) + if er := plugin.ipamInvoker.Delete(&result.IPs[0].Address, nwCfg, args, nwInfo.Options); er != nil { + err = plugin.Errorf("Failed to cleanup when NwInfo was nil with error %v, after Add failed with error %w", er, err) + } } if resultV6 != nil && len(resultV6.IPs) > 0 { - plugin.ipamInvoker.Delete(&resultV6.IPs[0].Address, nwCfg, args, nwInfo.Options) + if er := plugin.ipamInvoker.Delete(&resultV6.IPs[0].Address, nwCfg, args, nwInfo.Options); er != nil { + err = plugin.Errorf("Failed to cleanup when NwInfo was nil with error %v, after Add failed with error %w", er, err) + } } } }() diff --git a/cni/network/network_test.go b/cni/network/network_test.go index 58dc87b388..a451dcbf1c 100644 --- a/cni/network/network_test.go +++ b/cni/network/network_test.go @@ -100,8 +100,11 @@ func TestGetSimpleState(t *testing.T) { ep1 := getTestEndpoint("podname1", "podnamespace1", "10.0.0.1/24", "podinterfaceid1", "testcontainerid1") ep2 := getTestEndpoint("podname2", "podnamespace2", "10.0.0.2/24", "podinterfaceid2", "testcontainerid2") - mockNetworkManager.CreateEndpoint(networkid, ep1) - mockNetworkManager.CreateEndpoint(networkid, ep2) + err := mockNetworkManager.CreateEndpoint(networkid, ep1) + require.NoError(t, err) + + err = mockNetworkManager.CreateEndpoint(networkid, ep2) + require.NoError(t, err) state, err := plugin.GetSimpleState() require.NoError(t, err) From f14802f095d567f032c8b09a4d635db394517b2b Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Mon, 7 Jun 2021 23:53:37 +0000 Subject: [PATCH 5/8] address some feedback --- Makefile | 6 +++ cni/api/api.go | 30 ++++++++++-- cni/client/client.go | 4 +- cni/client/client_common_test.go | 4 +- cni/client/client_integration_test.go | 16 ++----- cni/client/client_unit_test.go | 6 +-- cni/network/invoker_cns.go | 4 +- cni/network/network.go | 4 +- cni/network/network_test.go | 2 +- cni/network/plugin/main.go | 68 ++++++++++++++------------- cns/cnsclient/cnsclient_test.go | 6 +-- test/utils/utils.go | 6 +-- 12 files changed, 89 insertions(+), 67 deletions(-) diff --git a/Makefile b/Makefile index 6df11bf606..499552062a 100644 --- a/Makefile +++ b/Makefile @@ -462,6 +462,12 @@ PRETTYGOTEST := $(shell command -v gotest 2> /dev/null) test-all: go test -tags "unit integration" -coverpkg=./... -v -race -covermode atomic -failfast -coverprofile=coverage.out ./... +# run all tests +.PHONY: test-all +test-all: + go test -tags "unit integration" -coverpkg=./... -v -race -covermode atomic -failfast -coverprofile=coverage.out ./... + + # run all tests .PHONY: test-integration test-integration: diff --git a/cni/api/api.go b/cni/api/api.go index 94bb80ba7f..f73e9b140b 100644 --- a/cni/api/api.go +++ b/cni/api/api.go @@ -1,9 +1,15 @@ package api -import "net" +import ( + "encoding/json" + "net" + "os" -type NetworkInterfaceInfo struct { - PodName string + "github.com/Azure/azure-container-networking/log" +) + +type PodNetworkInterfaceInfo struct { + PodName string PodNamespace string PodInterfaceID string ContainerID string @@ -11,5 +17,21 @@ type NetworkInterfaceInfo struct { } type AzureCNIState struct { - ContainerInterfaces map[string]NetworkInterfaceInfo + ContainerInterfaces map[string]PodNetworkInterfaceInfo +} + +func (a *AzureCNIState) PrintResult() error { + b, err := json.MarshalIndent(a, "", " ") + if err != nil { + log.Errorf("Failed to unmarshall Azure CNI state, err:%v.\n", err) + } + + // write result to stdout to be captured by caller + _, err = os.Stdout.Write(b) + if err != nil { + log.Printf("Failed to write response to stdout %v", err) + return err + } + + return nil } diff --git a/cni/client/client.go b/cni/client/client.go index a041ce12c5..64c04907a3 100644 --- a/cni/client/client.go +++ b/cni/client/client.go @@ -30,12 +30,12 @@ func (c *CNIClient) GetState() (*api.AzureCNIState, error) { output, err := cmd.CombinedOutput() if err != nil { - return nil, fmt.Errorf("Failed to call Azure CNI bin with err: [%w], output: [%s]", err, string(output)) + return nil, fmt.Errorf("failed to call Azure CNI bin with err: [%w], output: [%s]", err, string(output)) } state := &api.AzureCNIState{} if err := json.Unmarshal(output, state); err != nil { - return nil, fmt.Errorf("Failed to decode response from Azure CNI when retrieving state: [%w], response from CNI: [%s]", err, string(output)) + return nil, fmt.Errorf("failed to decode response from Azure CNI when retrieving state: [%w], response from CNI: [%s]", err, string(output)) } return state, nil diff --git a/cni/client/client_common_test.go b/cni/client/client_common_test.go index 18063ee7f6..ccd331a825 100644 --- a/cni/client/client_common_test.go +++ b/cni/client/client_common_test.go @@ -8,10 +8,10 @@ import ( "github.com/Azure/azure-container-networking/cni/api" ) -func testGetNetworkInterfaceInfo(podinterfaceid, podname, podnamespace, containerid, ipwithcidr string) api.NetworkInterfaceInfo { +func testGetPodNetworkInterfaceInfo(podinterfaceid, podname, podnamespace, containerid, ipwithcidr string) api.PodNetworkInterfaceInfo { ip, ipnet, _ := net.ParseCIDR(ipwithcidr) ipnet.IP = ip - return api.NetworkInterfaceInfo{ + return api.PodNetworkInterfaceInfo{ PodName: podname, PodNamespace: podnamespace, PodInterfaceID: podinterfaceid, diff --git a/cni/client/client_integration_test.go b/cni/client/client_integration_test.go index e501a3d30e..6b678a999b 100644 --- a/cni/client/client_integration_test.go +++ b/cni/client/client_integration_test.go @@ -5,9 +5,7 @@ package client import ( "io" - "log" "os" - "os/user" "testing" "github.com/Azure/azure-container-networking/cni/api" @@ -16,14 +14,6 @@ import ( "k8s.io/utils/exec" ) -func isRoot() bool { - currentUser, err := user.Current() - if err != nil { - log.Fatalf("[isRoot] Unable to get current user: %s", err) - } - return currentUser.Username == "root" -} - func TestGetStateFromAzureCNI(t *testing.T) { testutils.RequireRootforTest(t) @@ -53,9 +43,9 @@ func TestGetStateFromAzureCNI(t *testing.T) { require.NoError(t, err) res := &api.AzureCNIState{ - ContainerInterfaces: map[string]api.NetworkInterfaceInfo{ - "3f813b02-eth0": testGetNetworkInterfaceInfo("3f813b02-eth0", "metrics-server-77c8679d7d-6ksdh", "kube-system", "3f813b029429b4e41a09ab33b6f6d365d2ed704017524c78d1d0dece33cdaf46", "10.241.0.17/16"), - "6e688597-eth0": testGetNetworkInterfaceInfo("6e688597-eth0", "tunnelfront-5d96f9b987-65xbn", "kube-system", "6e688597eafb97c83c84e402cc72b299bfb8aeb02021e4c99307a037352c0bed", "10.241.0.13/16"), + ContainerInterfaces: map[string]api.PodNetworkInterfaceInfo{ + "3f813b02-eth0": testGetPodNetworkInterfaceInfo("3f813b02-eth0", "metrics-server-77c8679d7d-6ksdh", "kube-system", "3f813b029429b4e41a09ab33b6f6d365d2ed704017524c78d1d0dece33cdaf46", "10.241.0.17/16"), + "6e688597-eth0": testGetPodNetworkInterfaceInfo("6e688597-eth0", "tunnelfront-5d96f9b987-65xbn", "kube-system", "6e688597eafb97c83c84e402cc72b299bfb8aeb02021e4c99307a037352c0bed", "10.241.0.13/16"), }, } diff --git a/cni/client/client_unit_test.go b/cni/client/client_unit_test.go index 94c47da9a2..bf39c5fc03 100644 --- a/cni/client/client_unit_test.go +++ b/cni/client/client_unit_test.go @@ -22,9 +22,9 @@ func TestGetState(t *testing.T) { require.NoError(t, err) res := &api.AzureCNIState{ - ContainerInterfaces: map[string]api.NetworkInterfaceInfo{ - "3f813b02-eth0": testGetNetworkInterfaceInfo("3f813b02-eth0", "metrics-server-77c8679d7d-6ksdh", "kube-system", "3f813b029429b4e41a09ab33b6f6d365d2ed704017524c78d1d0dece33cdaf46", "10.241.0.17/16"), - "6e688597-eth0": testGetNetworkInterfaceInfo("6e688597-eth0", "tunnelfront-5d96f9b987-65xbn", "kube-system", "6e688597eafb97c83c84e402cc72b299bfb8aeb02021e4c99307a037352c0bed", "10.241.0.13/16"), + ContainerInterfaces: map[string]api.PodNetworkInterfaceInfo{ + "3f813b02-eth0": testGetPodNetworkInterfaceInfo("3f813b02-eth0", "metrics-server-77c8679d7d-6ksdh", "kube-system", "3f813b029429b4e41a09ab33b6f6d365d2ed704017524c78d1d0dece33cdaf46", "10.241.0.17/16"), + "6e688597-eth0": testGetPodNetworkInterfaceInfo("6e688597-eth0", "tunnelfront-5d96f9b987-65xbn", "kube-system", "6e688597eafb97c83c84e402cc72b299bfb8aeb02021e4c99307a037352c0bed", "10.241.0.13/16"), }, } diff --git a/cni/network/invoker_cns.go b/cni/network/invoker_cns.go index 13c2f26134..3ae8ab329c 100644 --- a/cni/network/invoker_cns.go +++ b/cni/network/invoker_cns.go @@ -65,7 +65,7 @@ func (invoker *CNSIPAMInvoker) Add(nwCfg *cni.NetworkConfig, args *cniSkel.CmdAr InfraContainerID: args.ContainerID, } - log.Printf("Requesting IP for pod %v", podInfo) + log.Printf("Requesting IP for pod %v using ipconfig %v", podInfo, ipconfig) response, err := invoker.cnsClient.RequestIPAddress(&ipconfig) if err != nil { log.Printf("Failed to get IP address from CNS with error %v, response: %v", err, response) @@ -85,7 +85,7 @@ func (invoker *CNSIPAMInvoker) Add(nwCfg *cni.NetworkConfig, args *cniSkel.CmdAr // set the NC Primary IP in options options[network.SNATIPKey] = info.ncPrimaryIP - log.Printf("[cni-invoker-cns] Received info %+v v for pod %v", info, podInfo) + log.Printf("[cni-invoker-cns] Received info %+v for pod %v", info, podInfo) ncgw := net.ParseIP(info.ncGatewayIPAddress) if ncgw == nil { diff --git a/cni/network/network.go b/cni/network/network.go index b418935ba5..a9c4e8fd4a 100644 --- a/cni/network/network.go +++ b/cni/network/network.go @@ -157,7 +157,7 @@ func (plugin *netPlugin) Start(config *common.PluginConfig) error { func (plugin *netPlugin) GetSimpleState() (*api.AzureCNIState, error) { st := api.AzureCNIState{ - ContainerInterfaces: make(map[string]api.NetworkInterfaceInfo), + ContainerInterfaces: make(map[string]api.PodNetworkInterfaceInfo), } eps, err := plugin.nm.GetAllEndpoints("azure") @@ -167,7 +167,7 @@ func (plugin *netPlugin) GetSimpleState() (*api.AzureCNIState, error) { for _, ep := range eps { id := ep.Id - info := api.NetworkInterfaceInfo{ + info := api.PodNetworkInterfaceInfo{ PodName: ep.PODName, PodNamespace: ep.PODNameSpace, PodInterfaceID: ep.Id, diff --git a/cni/network/network_test.go b/cni/network/network_test.go index a451dcbf1c..2c0ee8deda 100644 --- a/cni/network/network_test.go +++ b/cni/network/network_test.go @@ -110,7 +110,7 @@ func TestGetSimpleState(t *testing.T) { require.NoError(t, err) res := &api.AzureCNIState{ - ContainerInterfaces: map[string]api.NetworkInterfaceInfo{ + ContainerInterfaces: map[string]api.PodNetworkInterfaceInfo{ ep1.Id: { PodInterfaceID: ep1.Id, PodName: ep1.PODName, diff --git a/cni/network/plugin/main.go b/cni/network/plugin/main.go index 49cadb6245..7ad1f229f2 100644 --- a/cni/network/plugin/main.go +++ b/cni/network/plugin/main.go @@ -171,6 +171,7 @@ func main() { upTime, err := platform.GetLastRebootTime() if err == nil { cniReport.VMUptime = upTime.Format("2006-01-02 15:04:05") + return } cniReport.GetReport(pluginName, version, ipamQueryURL) @@ -205,6 +206,10 @@ func main() { log.Errorf("Failed to uninitialize key-value store of network plugin, err:%v.\n", errUninit) } + if err != nil { + log.Printf("") + } + if recover() != nil { os.Exit(1) } @@ -227,34 +232,6 @@ func main() { panic("network plugin start fatal error") } - defer func() { - netPlugin.Stop() - - // release cni lock - if errUninit := netPlugin.Plugin.UninitializeKeyValueStore(false); errUninit != nil { - log.Errorf("Failed to uninitialize key-value store of network plugin, err:%v.\n", errUninit) - } - - executionTimeMs := time.Since(startTime).Milliseconds() - - if err != nil { - reportPluginError(reportManager, tb, err) - panic("network plugin execute fatal error") - } - - // Report CNI successfully finished execution. - reflect.ValueOf(reportManager.Report).Elem().FieldByName("CniSucceeded").SetBool(true) - reflect.ValueOf(reportManager.Report).Elem().FieldByName("OperationDuration").SetInt(executionTimeMs) - - if cniReport.ErrorMessage != "" || cniReport.EventMessage != "" { - if err = reportManager.SendReport(tb); err != nil { - log.Errorf("SendReport failed due to %v", err) - } else { - log.Printf("Sending report succeeded") - } - } - }() - // Check CNI_COMMAND value for logging purposes. cniCmd := os.Getenv(cni.Cmd) log.Printf("CNI_COMMAND environment variable set to %s", cniCmd) @@ -265,13 +242,14 @@ func main() { simpleState, err := netPlugin.GetSimpleState() if err != nil { log.Errorf("Failed to get Azure CNI state, err:%v.\n", err) + return } - b, err := json.Marshal(simpleState) + + err = simpleState.PrintResult() if err != nil { - log.Errorf("Failed to unmarshall Azure CNI state, err:%v.\n", err) + log.Errorf("Failed to print state result to stdout with err %v\n", err) } - log.Printf("State: %s", string(b)) - fmt.Printf("%s\n", string(b)) + return } @@ -281,4 +259,30 @@ func main() { } else if err = netPlugin.Execute(cni.PluginApi(netPlugin)); err != nil { log.Errorf("Failed to execute network plugin, err:%v.\n", err) } + + netPlugin.Stop() + + // release cni lock + if errUninit := netPlugin.Plugin.UninitializeKeyValueStore(false); errUninit != nil { + log.Errorf("Failed to uninitialize key-value store of network plugin, err:%v.\n", errUninit) + } + + executionTimeMs := time.Since(startTime).Milliseconds() + + if err != nil { + reportPluginError(reportManager, tb, err) + panic("network plugin execute fatal error") + } + + // Report CNI successfully finished execution. + reflect.ValueOf(reportManager.Report).Elem().FieldByName("CniSucceeded").SetBool(true) + reflect.ValueOf(reportManager.Report).Elem().FieldByName("OperationDuration").SetInt(executionTimeMs) + + if cniReport.ErrorMessage != "" || cniReport.EventMessage != "" { + if err = reportManager.SendReport(tb); err != nil { + log.Errorf("SendReport failed due to %v", err) + } else { + log.Printf("Sending report succeeded") + } + } } diff --git a/cns/cnsclient/cnsclient_test.go b/cns/cnsclient/cnsclient_test.go index 0185baeb85..4de17f8bdc 100644 --- a/cns/cnsclient/cnsclient_test.go +++ b/cns/cnsclient/cnsclient_test.go @@ -233,7 +233,7 @@ func TestCNSClientRequestAndRelease(t *testing.T) { } // request IP address - resp, err := cnsClient.RequestIPAddress(orchestratorContext) + resp, err := cnsClient.RequestIPAddress(&cns.IPConfigRequest{OrchestratorContext: orchestratorContext}) if err != nil { t.Fatalf("get IP from CNS failed with %+v", err) } @@ -301,7 +301,7 @@ func TestCNSClientPodContextApi(t *testing.T) { } // request IP address - _, err = cnsClient.RequestIPAddress(orchestratorContext) + _, err = cnsClient.RequestIPAddress(&cns.IPConfigRequest{OrchestratorContext: orchestratorContext}) if err != nil { t.Fatalf("get IP from CNS failed with %+v", err) } @@ -341,7 +341,7 @@ func TestCNSClientDebugAPI(t *testing.T) { } // request IP address - _, err1 := cnsClient.RequestIPAddress(orchestratorContext) + _, err1 := cnsClient.RequestIPAddress(&cns.IPConfigRequest{OrchestratorContext: orchestratorContext}) if err1 != nil { t.Fatalf("get IP from CNS failed with %+v", err1) } diff --git a/test/utils/utils.go b/test/utils/utils.go index e9b8295aa5..59adc9f0c6 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -48,7 +48,7 @@ func VerifyCallsMatch(t *testing.T, calls []TestCmd, fexec *fakeexec.FakeExec, f } } -func isRoot() bool { +func isCurrentUserRoot() bool { currentUser, err := user.Current() if err != nil { log.Printf("Failed to get current user") @@ -60,13 +60,13 @@ func isRoot() bool { } func RequireRootforTest(t *testing.T) { - if !isRoot() { + if !isCurrentUserRoot() { t.Fatalf("Test [%s] requires root!", t.Name()) } } func RequireRootforTestMain(m *testing.M) { - if !isRoot() { + if !isCurrentUserRoot() { log.Printf("These tests require root!") os.Exit(1) } From 3cd0af1a1c2ef61dd8e5418093f5447f9807008d Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Tue, 8 Jun 2021 16:28:10 +0000 Subject: [PATCH 6/8] fix test path and linting --- cni/client/client_integration_test.go | 2 +- cns/cnsclient/cnsclient.go | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cni/client/client_integration_test.go b/cni/client/client_integration_test.go index 6b678a999b..913b5316bb 100644 --- a/cni/client/client_integration_test.go +++ b/cni/client/client_integration_test.go @@ -18,7 +18,7 @@ func TestGetStateFromAzureCNI(t *testing.T) { testutils.RequireRootforTest(t) // copy test state file to /var/run/azure-vnet.json - in, err := os.Open("./azure-vnet-test.json") + in, err := os.Open("./testresources/azure-vnet-test.json") require.NoError(t, err) defer in.Close() diff --git a/cns/cnsclient/cnsclient.go b/cns/cnsclient/cnsclient.go index 1e303ae44b..c7d7949fdd 100644 --- a/cns/cnsclient/cnsclient.go +++ b/cns/cnsclient/cnsclient.go @@ -224,7 +224,9 @@ func (cnsClient *CNSClient) RequestIPAddress(ipconfig *cns.IPConfigRequest) (*cn defer func() { if err != nil { - cnsClient.ReleaseIPAddress(ipconfig) + if er := cnsClient.ReleaseIPAddress(ipconfig); er != nil { + log.Printf("failed to release IP address [%v] after failed add [%w]", er, err) + } } }() From d8ec19ee0423fdddf3f2a222fc74d31a3dfaf6cb Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Tue, 8 Jun 2021 23:41:55 +0000 Subject: [PATCH 7/8] address feedback and logging --- Makefile | 5 ----- cni/api/api.go | 4 ++++ cni/client/client.go | 25 ++++++++++++++++++------- cni/client/client_integration_test.go | 2 +- cni/cni.go | 2 +- cni/ipam/ipam_test.go | 11 ++++++----- cni/network/invoker_cns.go | 2 +- cni/network/network.go | 4 ++-- cni/network/network_test.go | 4 ++-- cni/network/plugin/main.go | 10 +++------- cns/cnsclient/cnsclient.go | 2 +- 11 files changed, 39 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index 499552062a..2c49025591 100644 --- a/Makefile +++ b/Makefile @@ -462,11 +462,6 @@ PRETTYGOTEST := $(shell command -v gotest 2> /dev/null) test-all: go test -tags "unit integration" -coverpkg=./... -v -race -covermode atomic -failfast -coverprofile=coverage.out ./... -# run all tests -.PHONY: test-all -test-all: - go test -tags "unit integration" -coverpkg=./... -v -race -covermode atomic -failfast -coverprofile=coverage.out ./... - # run all tests .PHONY: test-integration diff --git a/cni/api/api.go b/cni/api/api.go index f73e9b140b..3978c60ecb 100644 --- a/cni/api/api.go +++ b/cni/api/api.go @@ -16,6 +16,10 @@ type PodNetworkInterfaceInfo struct { IPAddresses []net.IPNet } +type CNIState interface { + PrintResult() error +} + type AzureCNIState struct { ContainerInterfaces map[string]PodNetworkInterfaceInfo } diff --git a/cni/client/client.go b/cni/client/client.go index 64c04907a3..80f9ad3321 100644 --- a/cni/client/client.go +++ b/cni/client/client.go @@ -7,25 +7,36 @@ import ( "github.com/Azure/azure-container-networking/cni" "github.com/Azure/azure-container-networking/cni/api" + "github.com/Azure/azure-container-networking/log" utilexec "k8s.io/utils/exec" ) -type CNIClient struct { +const ( + azureVnetBinName = "./azure-vnet" + azureVnetBinDirectory = "/opt/cni/bin" +) + +type CNIClient interface { + GetEndpointState() (api.CNIState, error) +} + +type AzureCNIClient struct { exec utilexec.Interface } -func NewCNIClient(exec utilexec.Interface) *CNIClient { - return &CNIClient{ +func NewCNIClient(exec utilexec.Interface) *AzureCNIClient { + return &AzureCNIClient{ exec: exec, } } -func (c *CNIClient) GetState() (*api.AzureCNIState, error) { - cmd := c.exec.Command("./azure-vnet") - cmd.SetDir("/opt/cni/bin") +func (c *AzureCNIClient) GetEndpointState() (api.CNIState, error) { + cmd := c.exec.Command(azureVnetBinName) + cmd.SetDir(azureVnetBinDirectory) envs := os.Environ() - envs = append(envs, fmt.Sprintf("%s=%s", cni.Cmd, cni.CmdState)) + envs = append(envs, fmt.Sprintf("%s=%s", cni.Cmd, cni.CmdGetEndpointsState)) + log.Printf("Using envs: %v", envs) cmd.SetEnv(envs) output, err := cmd.CombinedOutput() diff --git a/cni/client/client_integration_test.go b/cni/client/client_integration_test.go index 913b5316bb..a0ec22bcb2 100644 --- a/cni/client/client_integration_test.go +++ b/cni/client/client_integration_test.go @@ -39,7 +39,7 @@ func TestGetStateFromAzureCNI(t *testing.T) { realexec := exec.New() c := NewCNIClient(realexec) - state, err := c.GetState() + state, err := c.GetEndpointState() require.NoError(t, err) res := &api.AzureCNIState{ diff --git a/cni/cni.go b/cni/cni.go index 12bced5596..bfcd1b1854 100644 --- a/cni/cni.go +++ b/cni/cni.go @@ -16,7 +16,7 @@ const ( CmdUpdate = "UPDATE" // nonstandard CNI spec command, used to dump CNI state to stdout - CmdState = "GET_STATE" + CmdGetEndpointsState = "GET_ENDPOINT_STATE" // CNI errors. ErrRuntime = 100 diff --git a/cni/ipam/ipam_test.go b/cni/ipam/ipam_test.go index d480e31b1e..cc6c32ef17 100644 --- a/cni/ipam/ipam_test.go +++ b/cni/ipam/ipam_test.go @@ -6,17 +6,18 @@ package ipam import ( "encoding/json" "fmt" - cniSkel "github.com/containernetworking/cni/pkg/skel" - cniTypesCurr "github.com/containernetworking/cni/pkg/types/current" - "github.com/google/uuid" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" "net" "net/http" "net/url" "testing" "time" + cniSkel "github.com/containernetworking/cni/pkg/skel" + cniTypesCurr "github.com/containernetworking/cni/pkg/types/current" + "github.com/google/uuid" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/Azure/azure-container-networking/common" ) diff --git a/cni/network/invoker_cns.go b/cni/network/invoker_cns.go index 3ae8ab329c..2c593de6a4 100644 --- a/cni/network/invoker_cns.go +++ b/cni/network/invoker_cns.go @@ -65,7 +65,7 @@ func (invoker *CNSIPAMInvoker) Add(nwCfg *cni.NetworkConfig, args *cniSkel.CmdAr InfraContainerID: args.ContainerID, } - log.Printf("Requesting IP for pod %v using ipconfig %v", podInfo, ipconfig) + log.Printf("Requesting IP for pod %+v using ipconfig %+v", podInfo, ipconfig) response, err := invoker.cnsClient.RequestIPAddress(&ipconfig) if err != nil { log.Printf("Failed to get IP address from CNS with error %v, response: %v", err, response) diff --git a/cni/network/network.go b/cni/network/network.go index a9c4e8fd4a..24eaa5ba79 100644 --- a/cni/network/network.go +++ b/cni/network/network.go @@ -155,12 +155,12 @@ func (plugin *netPlugin) Start(config *common.PluginConfig) error { return nil } -func (plugin *netPlugin) GetSimpleState() (*api.AzureCNIState, error) { +func (plugin *netPlugin) GetAllEndpointState(networkid string) (api.CNIState, error) { st := api.AzureCNIState{ ContainerInterfaces: make(map[string]api.PodNetworkInterfaceInfo), } - eps, err := plugin.nm.GetAllEndpoints("azure") + eps, err := plugin.nm.GetAllEndpoints(networkid) if err != nil { return nil, err } diff --git a/cni/network/network_test.go b/cni/network/network_test.go index 2c0ee8deda..16b1c2f818 100644 --- a/cni/network/network_test.go +++ b/cni/network/network_test.go @@ -93,7 +93,7 @@ func getTestEndpoint(podname, podnamespace, ipwithcidr, podinterfaceid, infracon return &ep } -func TestGetSimpleState(t *testing.T) { +func TestGetAllEndpointState(t *testing.T) { plugin, mockNetworkManager := getTestResources() networkid := "azure" @@ -106,7 +106,7 @@ func TestGetSimpleState(t *testing.T) { err = mockNetworkManager.CreateEndpoint(networkid, ep2) require.NoError(t, err) - state, err := plugin.GetSimpleState() + state, err := plugin.GetAllEndpointState(networkid) require.NoError(t, err) res := &api.AzureCNIState{ diff --git a/cni/network/plugin/main.go b/cni/network/plugin/main.go index 7ad1f229f2..dcab651374 100644 --- a/cni/network/plugin/main.go +++ b/cni/network/plugin/main.go @@ -206,10 +206,6 @@ func main() { log.Errorf("Failed to uninitialize key-value store of network plugin, err:%v.\n", errUninit) } - if err != nil { - log.Printf("") - } - if recover() != nil { os.Exit(1) } @@ -237,9 +233,9 @@ func main() { log.Printf("CNI_COMMAND environment variable set to %s", cniCmd) // used to dump state - if cniCmd == cni.CmdState { + if cniCmd == cni.CmdGetEndpointsState { log.Printf("Retrieving state") - simpleState, err := netPlugin.GetSimpleState() + simpleState, err := netPlugin.GetAllEndpointState("azure") if err != nil { log.Errorf("Failed to get Azure CNI state, err:%v.\n", err) return @@ -254,7 +250,7 @@ func main() { } handled, err := handleIfCniUpdate(netPlugin.Update) - if handled == true { + if handled { log.Printf("CNI UPDATE finished.") } else if err = netPlugin.Execute(cni.PluginApi(netPlugin)); err != nil { log.Errorf("Failed to execute network plugin, err:%v.\n", err) diff --git a/cns/cnsclient/cnsclient.go b/cns/cnsclient/cnsclient.go index c7d7949fdd..71867cccaf 100644 --- a/cns/cnsclient/cnsclient.go +++ b/cns/cnsclient/cnsclient.go @@ -225,7 +225,7 @@ func (cnsClient *CNSClient) RequestIPAddress(ipconfig *cns.IPConfigRequest) (*cn defer func() { if err != nil { if er := cnsClient.ReleaseIPAddress(ipconfig); er != nil { - log.Printf("failed to release IP address [%v] after failed add [%w]", er, err) + log.Errorf("failed to release IP address [%v] after failed add [%v]", er, err) } } }() From b73a19346d8af30184a0769046755ede2f3023a9 Mon Sep 17 00:00:00 2001 From: Mathew Merrick Date: Wed, 9 Jun 2021 00:36:35 +0000 Subject: [PATCH 8/8] remove return and rename to PodEndpointID --- Makefile | 2 +- cni/api/api.go | 2 +- cni/client/client.go | 5 +- cni/client/client_common_test.go | 10 +- cni/client/client_integration_test.go | 1 + cni/client/client_unit_test.go | 6 +- cni/client/testresources/azure-vnet-test.json | 155 ++++++++++++++++++ cni/network/invoker_azure.go | 2 +- cni/network/network.go | 2 +- cni/network/network_test.go | 4 +- cni/network/plugin/main.go | 1 - 11 files changed, 173 insertions(+), 17 deletions(-) create mode 100644 cni/client/testresources/azure-vnet-test.json diff --git a/Makefile b/Makefile index 2c49025591..bc59dcf4ab 100644 --- a/Makefile +++ b/Makefile @@ -460,7 +460,7 @@ PRETTYGOTEST := $(shell command -v gotest 2> /dev/null) # run all tests .PHONY: test-all test-all: - go test -tags "unit integration" -coverpkg=./... -v -race -covermode atomic -failfast -coverprofile=coverage.out ./... + go test -tags "unit" -coverpkg=./... -v -race -covermode atomic -failfast -coverprofile=coverage.out ./... # run all tests diff --git a/cni/api/api.go b/cni/api/api.go index 3978c60ecb..0d062331f0 100644 --- a/cni/api/api.go +++ b/cni/api/api.go @@ -11,7 +11,7 @@ import ( type PodNetworkInterfaceInfo struct { PodName string PodNamespace string - PodInterfaceID string + PodEndpointId string ContainerID string IPAddresses []net.IPNet } diff --git a/cni/client/client.go b/cni/client/client.go index 80f9ad3321..bce421b1c5 100644 --- a/cni/client/client.go +++ b/cni/client/client.go @@ -35,8 +35,9 @@ func (c *AzureCNIClient) GetEndpointState() (api.CNIState, error) { cmd.SetDir(azureVnetBinDirectory) envs := os.Environ() - envs = append(envs, fmt.Sprintf("%s=%s", cni.Cmd, cni.CmdGetEndpointsState)) - log.Printf("Using envs: %v", envs) + cmdenv := fmt.Sprintf("%s=%s", cni.Cmd, cni.CmdGetEndpointsState) + log.Printf("Setting cmd to %s", cmdenv) + envs = append(envs, cmdenv) cmd.SetEnv(envs) output, err := cmd.CombinedOutput() diff --git a/cni/client/client_common_test.go b/cni/client/client_common_test.go index ccd331a825..bb2539a446 100644 --- a/cni/client/client_common_test.go +++ b/cni/client/client_common_test.go @@ -8,14 +8,14 @@ import ( "github.com/Azure/azure-container-networking/cni/api" ) -func testGetPodNetworkInterfaceInfo(podinterfaceid, podname, podnamespace, containerid, ipwithcidr string) api.PodNetworkInterfaceInfo { +func testGetPodNetworkInterfaceInfo(podendpointid, podname, podnamespace, containerid, ipwithcidr string) api.PodNetworkInterfaceInfo { ip, ipnet, _ := net.ParseCIDR(ipwithcidr) ipnet.IP = ip return api.PodNetworkInterfaceInfo{ - PodName: podname, - PodNamespace: podnamespace, - PodInterfaceID: podinterfaceid, - ContainerID: containerid, + PodName: podname, + PodNamespace: podnamespace, + PodEndpointId: podendpointid, + ContainerID: containerid, IPAddresses: []net.IPNet{ *ipnet, }, diff --git a/cni/client/client_integration_test.go b/cni/client/client_integration_test.go index a0ec22bcb2..9af07595e6 100644 --- a/cni/client/client_integration_test.go +++ b/cni/client/client_integration_test.go @@ -14,6 +14,7 @@ import ( "k8s.io/utils/exec" ) +// todo: enable this test in CI, requires built azure vnet func TestGetStateFromAzureCNI(t *testing.T) { testutils.RequireRootforTest(t) diff --git a/cni/client/client_unit_test.go b/cni/client/client_unit_test.go index bf39c5fc03..dc39ebf591 100644 --- a/cni/client/client_unit_test.go +++ b/cni/client/client_unit_test.go @@ -12,13 +12,13 @@ import ( func TestGetState(t *testing.T) { calls := []testutils.TestCmd{ - {Cmd: []string{"./azure-vnet"}, Stdout: `{"ContainerInterfaces":{"3f813b02-eth0":{"PodName":"metrics-server-77c8679d7d-6ksdh","PodNamespace":"kube-system","PodInterfaceID":"3f813b02-eth0","ContainerID":"3f813b029429b4e41a09ab33b6f6d365d2ed704017524c78d1d0dece33cdaf46","IPAddresses":[{"IP":"10.241.0.17","Mask":"//8AAA=="}]},"6e688597-eth0":{"PodName":"tunnelfront-5d96f9b987-65xbn","PodNamespace":"kube-system","PodInterfaceID":"6e688597-eth0","ContainerID":"6e688597eafb97c83c84e402cc72b299bfb8aeb02021e4c99307a037352c0bed","IPAddresses":[{"IP":"10.241.0.13","Mask":"//8AAA=="}]}}}`}, + {Cmd: []string{"./azure-vnet"}, Stdout: `{"ContainerInterfaces":{"3f813b02-eth0":{"PodName":"metrics-server-77c8679d7d-6ksdh","PodNamespace":"kube-system","PodEndpointID":"3f813b02-eth0","ContainerID":"3f813b029429b4e41a09ab33b6f6d365d2ed704017524c78d1d0dece33cdaf46","IPAddresses":[{"IP":"10.241.0.17","Mask":"//8AAA=="}]},"6e688597-eth0":{"PodName":"tunnelfront-5d96f9b987-65xbn","PodNamespace":"kube-system","PodEndpointID":"6e688597-eth0","ContainerID":"6e688597eafb97c83c84e402cc72b299bfb8aeb02021e4c99307a037352c0bed","IPAddresses":[{"IP":"10.241.0.13","Mask":"//8AAA=="}]}}}`}, } fakeexec, _ := testutils.GetFakeExecWithScripts(calls) c := NewCNIClient(fakeexec) - state, err := c.GetState() + state, err := c.GetEndpointState() require.NoError(t, err) res := &api.AzureCNIState{ @@ -28,5 +28,5 @@ func TestGetState(t *testing.T) { }, } - require.Exactly(t, res, state) + require.Equal(t, res, state) } diff --git a/cni/client/testresources/azure-vnet-test.json b/cni/client/testresources/azure-vnet-test.json new file mode 100644 index 0000000000..dceefe71a6 --- /dev/null +++ b/cni/client/testresources/azure-vnet-test.json @@ -0,0 +1,155 @@ +{ + "Network": { + "Version": "v1.2.6", + "TimeStamp": "2021-06-04T17:15:58.638215441Z", + "ExternalInterfaces": { + "eth0": { + "Name": "eth0", + "Networks": { + "azure": { + "Id": "azure", + "Mode": "transparent", + "VlanId": 0, + "Subnets": [ + { + "Family": 2, + "Prefix": { + "IP": "10.240.0.0", + "Mask": "//8AAA==" + }, + "Gateway": "10.241.0.1", + "PrimaryIP": "" + } + ], + "Endpoints": { + "3f813b02-eth0": { + "Id": "3f813b02-eth0", + "SandboxKey": "", + "IfName": "azvd805fb1b0f82", + "HostIfName": "azvd805fb1b0f8", + "MacAddress": "ipNAs8jK", + "InfraVnetIP": { + "IP": "", + "Mask": null + }, + "LocalIP": "", + "IPAddresses": [ + { + "IP": "10.241.0.17", + "Mask": "//8AAA==" + } + ], + "Gateways": [ + "0.0.0.0" + ], + "DNS": { + "Suffix": "", + "Servers": null, + "Options": null + }, + "Routes": [ + { + "Dst": { + "IP": "0.0.0.0", + "Mask": "AAAAAA==" + }, + "Src": "", + "Gw": "10.241.0.1", + "Protocol": 0, + "DevName": "", + "Scope": 0, + "Priority": 0 + } + ], + "VlanID": 0, + "EnableSnatOnHost": false, + "EnableInfraVnet": false, + "EnableMultitenancy": false, + "AllowInboundFromHostToNC": false, + "AllowInboundFromNCToHost": false, + "NetworkContainerID": "", + "NetworkNameSpace": "/var/run/netns/cni-e66c52d6-44be-555b-fb65-0b36296b6861", + "ContainerID": "3f813b029429b4e41a09ab33b6f6d365d2ed704017524c78d1d0dece33cdaf46", + "PODName": "metrics-server-77c8679d7d-6ksdh", + "PODNameSpace": "kube-system" + }, + "6e688597-eth0": { + "Id": "6e688597-eth0", + "SandboxKey": "", + "IfName": "azvc214c1237ce2", + "HostIfName": "azvc214c1237ce", + "MacAddress": "ZjL4HSJ+", + "InfraVnetIP": { + "IP": "", + "Mask": null + }, + "LocalIP": "", + "IPAddresses": [ + { + "IP": "10.241.0.13", + "Mask": "//8AAA==" + } + ], + "Gateways": [ + "0.0.0.0" + ], + "DNS": { + "Suffix": "", + "Servers": null, + "Options": null + }, + "Routes": [ + { + "Dst": { + "IP": "0.0.0.0", + "Mask": "AAAAAA==" + }, + "Src": "", + "Gw": "10.241.0.1", + "Protocol": 0, + "DevName": "", + "Scope": 0, + "Priority": 0 + } + ], + "VlanID": 0, + "EnableSnatOnHost": false, + "EnableInfraVnet": false, + "EnableMultitenancy": false, + "AllowInboundFromHostToNC": false, + "AllowInboundFromNCToHost": false, + "NetworkContainerID": "", + "NetworkNameSpace": "/var/run/netns/cni-56872dcd-b3ab-fc90-ccd8-6a6dd11d56cf", + "ContainerID": "6e688597eafb97c83c84e402cc72b299bfb8aeb02021e4c99307a037352c0bed", + "PODName": "tunnelfront-5d96f9b987-65xbn", + "PODNameSpace": "kube-system" + } + }, + "DNS": { + "Suffix": "", + "Servers": null, + "Options": null + }, + "EnableSnatOnHost": false, + "NetNs": "", + "SnatBridgeIP": "" + } + }, + "Subnets": [ + "10.240.0.0/16" + ], + "BridgeName": "", + "DNSInfo": { + "Suffix": "", + "Servers": null, + "Options": null + }, + "MacAddress": "AA06xXdb", + "IPAddresses": null, + "Routes": null, + "IPv4Gateway": "0.0.0.0", + "IPv6Gateway": "::" + } + } + } +} diff --git a/cni/network/invoker_azure.go b/cni/network/invoker_azure.go index ee3d821d06..0850755977 100644 --- a/cni/network/invoker_azure.go +++ b/cni/network/invoker_azure.go @@ -45,7 +45,7 @@ func (invoker *AzureIPAMInvoker) Add(nwCfg *cni.NetworkConfig, _ *cniSkel.CmdArg result, err = invoker.plugin.DelegateAdd(nwCfg.Ipam.Type, nwCfg) if err != nil { err = invoker.plugin.Errorf("Failed to allocate pool: %v", err) - return nil, nil, err + return nil, nil, err } defer func() { diff --git a/cni/network/network.go b/cni/network/network.go index 24eaa5ba79..6456142f35 100644 --- a/cni/network/network.go +++ b/cni/network/network.go @@ -170,7 +170,7 @@ func (plugin *netPlugin) GetAllEndpointState(networkid string) (api.CNIState, er info := api.PodNetworkInterfaceInfo{ PodName: ep.PODName, PodNamespace: ep.PODNameSpace, - PodInterfaceID: ep.Id, + PodEndpointId: ep.Id, ContainerID: ep.ContainerID, IPAddresses: ep.IPAddresses, } diff --git a/cni/network/network_test.go b/cni/network/network_test.go index 16b1c2f818..308b125101 100644 --- a/cni/network/network_test.go +++ b/cni/network/network_test.go @@ -112,14 +112,14 @@ func TestGetAllEndpointState(t *testing.T) { res := &api.AzureCNIState{ ContainerInterfaces: map[string]api.PodNetworkInterfaceInfo{ ep1.Id: { - PodInterfaceID: ep1.Id, + PodEndpointId: ep1.Id, PodName: ep1.PODName, PodNamespace: ep1.PODNameSpace, ContainerID: ep1.ContainerID, IPAddresses: ep1.IPAddresses, }, ep2.Id: { - PodInterfaceID: ep2.Id, + PodEndpointId: ep2.Id, PodName: ep2.PODName, PodNamespace: ep2.PODNameSpace, ContainerID: ep2.ContainerID, diff --git a/cni/network/plugin/main.go b/cni/network/plugin/main.go index dcab651374..d3cf147c13 100644 --- a/cni/network/plugin/main.go +++ b/cni/network/plugin/main.go @@ -171,7 +171,6 @@ func main() { upTime, err := platform.GetLastRebootTime() if err == nil { cniReport.VMUptime = upTime.Format("2006-01-02 15:04:05") - return } cniReport.GetReport(pluginName, version, ipamQueryURL)