Skip to content
Permalink
Browse files

Improve error/debug message

This diff changes error message with fixed format for easy-to-read
for users.
  • Loading branch information...
s1061123 authored and dougbtv committed Oct 2, 2019
1 parent f4431cd commit 0a2f7b18d3151e2480ab416bb1aca08e0d72cfa5
Showing with 113 additions and 109 deletions.
  1. +5 −5 checkpoint/checkpoint.go
  2. +28 −28 k8sclient/k8sclient.go
  3. +11 −7 k8sclient/k8sclient_test.go
  4. +7 −7 kubeletclient/kubeletclient.go
  5. +38 −38 multus/multus.go
  6. +1 −1 multus/multus_test.go
  7. +23 −23 types/conf.go
@@ -64,7 +64,7 @@ func getCheckpoint(filePath string) (types.ResourceClient, error) {
if err != nil {
return nil, err
}
logging.Debugf("getCheckpoint(): created checkpoint instance with file: %s", filePath)
logging.Debugf("getCheckpoint: created checkpoint instance with file: %s", filePath)
return cp, nil
}

@@ -74,15 +74,15 @@ func (cp *checkpoint) getPodEntries() error {
cpd := &checkpointFileData{}
rawBytes, err := ioutil.ReadFile(cp.fileName)
if err != nil {
return logging.Errorf("getPodEntries(): error reading file %s\n%v\n", checkPointfile, err)
return logging.Errorf("getPodEntries: error reading file %s\n%v\n", checkPointfile, err)
}

if err = json.Unmarshal(rawBytes, cpd); err != nil {
return logging.Errorf("getPodEntries(): error unmarshalling raw bytes %v", err)
return logging.Errorf("getPodEntries: error unmarshalling raw bytes %v", err)
}

cp.podEntires = cpd.Data.PodDeviceEntries
logging.Debugf("getPodEntries(): podEntires %+v", cp.podEntires)
logging.Debugf("getPodEntries: podEntires %+v", cp.podEntires)
return nil
}

@@ -92,7 +92,7 @@ func (cp *checkpoint) GetPodResourceMap(pod *v1.Pod) (map[string]*types.Resource
resourceMap := make(map[string]*types.ResourceInfo)

if podID == "" {
return nil, logging.Errorf("GetPodResourceMap(): invalid Pod cannot be empty")
return nil, logging.Errorf("GetPodResourceMap: invalid Pod cannot be empty")
}
for _, pod := range cp.podEntires {
if pod.PodUID == podID {
@@ -93,7 +93,7 @@ func SetNetworkStatus(client KubeClient, k8sArgs *types.K8sArgs, netStatus []*ty
if client == nil {
if len(conf.Delegates) == 0 {
// No available kube client and no delegates, we can't do anything
return logging.Errorf("must have either Kubernetes config or delegates, refer to Multus documentation for usage instructions")
return logging.Errorf("SetNetworkStatus: must have either Kubernetes config or delegates")
}
logging.Debugf("SetNetworkStatus: kube client info is not defined, skip network status setup")
return nil
@@ -150,7 +150,7 @@ func setPodNetworkAnnotation(client KubeClient, namespace string, pod *v1.Pod, n
pod, err = client.UpdatePodStatus(pod)
return err
}); resultErr != nil {
return nil, logging.Errorf("status update failed for pod %s/%s: %v", pod.Namespace, pod.Name, resultErr)
return nil, logging.Errorf("setPodNetworkAnnotation: status update failed for pod %s/%s: %v", pod.Namespace, pod.Name, resultErr)
}
return pod, nil
}
@@ -168,15 +168,15 @@ func parsePodNetworkObjectName(podnetwork string) (string, string, string, error
} else if len(slashItems) == 1 {
networkName = slashItems[0]
} else {
return "", "", "", logging.Errorf("Invalid network object (failed at '/')")
return "", "", "", logging.Errorf("parsePodNetworkObjectName: Invalid network object (failed at '/')")
}

atItems := strings.Split(networkName, "@")
networkName = strings.TrimSpace(atItems[0])
if len(atItems) == 2 {
netIfName = strings.TrimSpace(atItems[1])
} else if len(atItems) != 1 {
return "", "", "", logging.Errorf("Invalid network object (failed at '@')")
return "", "", "", logging.Errorf("parsePodNetworkObjectName: Invalid network object (failed at '@')")
}

// Check and see if each item matches the specification for valid attachment name.
@@ -188,7 +188,7 @@ func parsePodNetworkObjectName(podnetwork string) (string, string, string, error
for i := range allItems {
matched, _ := regexp.MatchString("^[a-z0-9]([-a-z0-9]*[a-z0-9])?$", allItems[i])
if !matched && len([]rune(allItems[i])) > 0 {
return "", "", "", logging.Errorf(fmt.Sprintf("Failed to parse: one or more items did not match comma-delimited format (must consist of lower case alphanumeric characters). Must start and end with an alphanumeric character), mismatch @ '%v'", allItems[i]))
return "", "", "", logging.Errorf(fmt.Sprintf("parsePodNetworkObjectName: Failed to parse: one or more items did not match comma-delimited format (must consist of lower case alphanumeric characters). Must start and end with an alphanumeric character), mismatch @ '%v'", allItems[i]))
}
}

@@ -201,7 +201,7 @@ func parsePodNetworkAnnotation(podNetworks, defaultNamespace string) ([]*types.N

logging.Debugf("parsePodNetworkAnnotation: %s, %s", podNetworks, defaultNamespace)
if podNetworks == "" {
return nil, logging.Errorf("parsePodNetworkAnnotation: pod annotation not having \"network\" as key, refer Multus README.md for the usage guide")
return nil, logging.Errorf("parsePodNetworkAnnotation: pod annotation does not have \"network\" as key")
}

if strings.IndexAny(podNetworks, "[{\"") >= 0 {
@@ -253,17 +253,17 @@ func getCNIConfigFromFile(name string, confdir string) ([]byte, error) {
files, err := libcni.ConfFiles(confdir, []string{".conf", ".json", ".conflist"})
switch {
case err != nil:
return nil, logging.Errorf("No networks found in %s", confdir)
return nil, logging.Errorf("getCNIConfigFromFile: no networks found in %s", confdir)
case len(files) == 0:
return nil, logging.Errorf("No networks found in %s", confdir)
return nil, logging.Errorf("getCNIConfigFromFile: no networks found in %s", confdir)
}

for _, confFile := range files {
var confList *libcni.NetworkConfigList
if strings.HasSuffix(confFile, ".conflist") {
confList, err = libcni.ConfListFromFile(confFile)
if err != nil {
return nil, logging.Errorf("Error loading CNI conflist file %s: %v", confFile, err)
return nil, logging.Errorf("getCNIConfigFromFile: error loading CNI conflist file %s: %v", confFile, err)
}

if confList.Name == name || name == "" {
@@ -273,21 +273,21 @@ func getCNIConfigFromFile(name string, confdir string) ([]byte, error) {
} else {
conf, err := libcni.ConfFromFile(confFile)
if err != nil {
return nil, logging.Errorf("Error loading CNI config file %s: %v", confFile, err)
return nil, logging.Errorf("getCNIConfigFromFile: error loading CNI config file %s: %v", confFile, err)
}

if conf.Network.Name == name || name == "" {
// Ensure the config has a "type" so we know what plugin to run.
// Also catches the case where somebody put a conflist into a conf file.
if conf.Network.Type == "" {
return nil, logging.Errorf("Error loading CNI config file %s: no 'type'; perhaps this is a .conflist?", confFile)
return nil, logging.Errorf("getCNIConfigFromFile: error loading CNI config file %s: does not have a 'type' key; perhaps this is a .conflist?", confFile)
}
return conf.Bytes, nil
}
}
}

return nil, logging.Errorf("no network available in the name %s in cni dir %s", name, confdir)
return nil, logging.Errorf("getCNIConfigFromFile: no network available with the name %s in cni dir %s", name, confdir)
}

// getCNIConfigFromSpec reads a CNI JSON configuration from the NetworkAttachmentDefinition
@@ -327,15 +327,15 @@ func cniConfigFromNetworkResource(customResource *types.NetworkAttachmentDefinit
// name as the custom resource
config, err = getCNIConfigFromFile(customResource.Metadata.Name, confdir)
if err != nil {
return nil, logging.Errorf("cniConfigFromNetworkResource: err in getCNIConfigFromFile: %v", err)
return nil, logging.Errorf("cniConfigFromNetworkResource: %v", err)
}
} else {
// Config contains a standard JSON-encoded CNI configuration
// or configuration list which defines the plugin chain to
// execute.
config, err = getCNIConfigFromSpec(customResource.Spec.Config, customResource.Metadata.Name)
if err != nil {
return nil, logging.Errorf("cniConfigFromNetworkResource: err in getCNIConfigFromSpec: %v", err)
return nil, logging.Errorf("cniConfigFromNetworkResource: %v", err)
}
}

@@ -348,12 +348,12 @@ func getKubernetesDelegate(client KubeClient, net *types.NetworkSelectionElement
rawPath := fmt.Sprintf("/apis/k8s.cni.cncf.io/v1/namespaces/%s/network-attachment-definitions/%s", net.Namespace, net.Name)
netData, err := client.GetRawWithPath(rawPath)
if err != nil {
return nil, resourceMap, logging.Errorf("getKubernetesDelegate: failed to get network resource, refer Multus README.md for the usage guide: %v", err)
return nil, resourceMap, logging.Errorf("getKubernetesDelegate: cannot find get a network-attachment-definition (%s) in namespace (%s): %v", net.Name, net.Namespace, err)
}

customResource := &types.NetworkAttachmentDefinition{}
if err := json.Unmarshal(netData, customResource); err != nil {
return nil, resourceMap, logging.Errorf("getKubernetesDelegate: failed to get the netplugin data: %v", err)
return nil, resourceMap, logging.Errorf("getKubernetesDelegate: failed to parse the network-attachment-definition: %v", err)
}

// Get resourceName annotation from NetworkAttachmentDefinition
@@ -372,7 +372,7 @@ func getKubernetesDelegate(client KubeClient, net *types.NetworkSelectionElement
if err != nil {
return nil, resourceMap, logging.Errorf("getKubernetesDelegate: failed to get resourceMap from ResourceClient: %v", err)
}
logging.Debugf("getKubernetesDelegate(): resourceMap instance: %+v", resourceMap)
logging.Debugf("getKubernetesDelegate: resourceMap instance: %+v", resourceMap)
}

entry, ok := resourceMap[resourceName]
@@ -433,7 +433,7 @@ func TryLoadPodDelegates(k8sArgs *types.K8sArgs, conf *types.NetConf, kubeClient
if kubeClient == nil {
if len(conf.Delegates) == 0 {
// No available kube client and no delegates, we can't do anything
return 0, nil, logging.Errorf("must have either Kubernetes config or delegates, refer Multus README.md for the usage guide")
return 0, nil, logging.Errorf("TryLoadPodDelegates: must have either Kubernetes config or delegates")
}
return 0, nil, nil
}
@@ -442,16 +442,16 @@ func TryLoadPodDelegates(k8sArgs *types.K8sArgs, conf *types.NetConf, kubeClient
// Get the pod info. If cannot get it, we use cached delegates
pod, err := kubeClient.GetPod(string(k8sArgs.K8S_POD_NAMESPACE), string(k8sArgs.K8S_POD_NAME))
if err != nil {
logging.Debugf("tryLoadK8sDelegates: Err in loading K8s cluster default network from pod annotation: %v, use cached delegates", err)
logging.Debugf("TryLoadPodDelegates: Err in loading K8s cluster default network from pod annotation: %v, use cached delegates", err)
return 0, nil, nil
}

delegate, err := tryLoadK8sPodDefaultNetwork(kubeClient, pod, conf)
if err != nil {
return 0, nil, logging.Errorf("tryLoadK8sDelegates: Err in loading K8s cluster default network from pod annotation: %v", err)
return 0, nil, logging.Errorf("TryLoadPodDelegates: error in loading K8s cluster default network from pod annotation: %v", err)
}
if delegate != nil {
logging.Debugf("tryLoadK8sDelegates: Overwrite the cluster default network with %v from pod annotations", delegate)
logging.Debugf("TryLoadPodDelegates: Overwrite the cluster default network with %v from pod annotations", delegate)

conf.Delegates[0] = delegate
}
@@ -464,7 +464,7 @@ func TryLoadPodDelegates(k8sArgs *types.K8sArgs, conf *types.NetConf, kubeClient
if _, ok := err.(*NoK8sNetworkError); ok {
return 0, clientInfo, nil
}
return 0, nil, logging.Errorf("Multus: Err in getting k8s network from pod: %v", err)
return 0, nil, logging.Errorf("TryLoadPodDelegates: error in getting k8s network from pod: %v", err)
}

if err = conf.AddDelegates(delegates); err != nil {
@@ -492,13 +492,13 @@ func GetK8sClient(kubeconfig string, kubeClient KubeClient) (KubeClient, error)
// uses the current context in kubeconfig
config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
return nil, logging.Errorf("GetK8sClient: failed to get context for the kubeconfig %v, refer Multus README.md for the usage guide: %v", kubeconfig, err)
return nil, logging.Errorf("GetK8sClient: failed to get context for the kubeconfig %v: %v", kubeconfig, err)
}
} else if os.Getenv("KUBERNETES_SERVICE_HOST") != "" && os.Getenv("KUBERNETES_SERVICE_PORT") != "" {
// Try in-cluster config where multus might be running in a kubernetes pod
config, err = rest.InClusterConfig()
if err != nil {
return nil, logging.Errorf("createK8sClient: failed to get context for in-cluster kube config, refer Multus README.md for the usage guide: %v", err)
return nil, logging.Errorf("GetK8sClient: failed to get context for in-cluster kube config: %v", err)
}
} else {
// No kubernetes config; assume we shouldn't talk to Kube at all
@@ -553,13 +553,13 @@ func GetNetworkDelegates(k8sclient KubeClient, pod *v1.Pod, networks []*types.Ne
// In the case that this is a mismatch when namespaceisolation is enabled, this should be an error.
if confnamespaceIsolation {
if defaultNamespace != net.Namespace {
return nil, logging.Errorf("GetPodNetwork: namespace isolation violation: podnamespace: %v / target namespace: %v", defaultNamespace, net.Namespace)
return nil, logging.Errorf("GetNetworkDelegates: namespace isolation enabled, annotation violates permission, pod is in namespace %v but refers to target namespace %v", defaultNamespace, net.Namespace)
}
}

delegate, updatedResourceMap, err := getKubernetesDelegate(k8sclient, net, confdir, pod, resourceMap)
if err != nil {
return nil, logging.Errorf("GetPodNetwork: failed getting the delegate: %v", err)
return nil, logging.Errorf("GetNetworkDelegates: failed getting the delegate: %v", err)
}
delegates = append(delegates, delegate)
resourceMap = updatedResourceMap
@@ -573,7 +573,7 @@ func getDefaultNetDelegateCRD(client KubeClient, net, confdir, namespace string)
rawPath := fmt.Sprintf("/apis/k8s.cni.cncf.io/v1/namespaces/%s/network-attachment-definitions/%s", namespace, net)
netData, err := client.GetRawWithPath(rawPath)
if err != nil {
return nil, logging.Errorf("getDefaultNetDelegateCRD: failed to get network resource, refer Multus README.md for the usage guide: %v", err)
return nil, logging.Errorf("getDefaultNetDelegateCRD: failed to get network resource: %v", err)
}

customResource := &types.NetworkAttachmentDefinition{}
@@ -650,7 +650,7 @@ func GetDefaultNetworks(k8sArgs *types.K8sArgs, conf *types.NetConf, kubeClient
if kubeClient == nil {
if len(conf.Delegates) == 0 {
// No available kube client and no delegates, we can't do anything
return logging.Errorf("must have either Kubernetes config or delegates, refer Multus README.md for the usage guide")
return logging.Errorf("GetDefaultNetworks: must have either Kubernetes config or delegates")
}
return nil
}
@@ -125,7 +125,7 @@ var _ = Describe("k8sclient operations", func() {
Expect(err).NotTo(HaveOccurred())
delegates, err := GetNetworkDelegates(kubeClient, pod, networks, tmpDir, false)
Expect(len(delegates)).To(Equal(0))
Expect(err).To(MatchError("GetPodNetwork: failed getting the delegate: getKubernetesDelegate: failed to get network resource, refer Multus README.md for the usage guide: resource not found"))
Expect(err).To(MatchError("GetNetworkDelegates: failed getting the delegate: getKubernetesDelegate: cannot find get a network-attachment-definition (net1) in namespace (test): resource not found"))
})

It("retrieves delegates from kubernetes using JSON format annotation", func() {
@@ -296,7 +296,7 @@ var _ = Describe("k8sclient operations", func() {
Expect(err).NotTo(HaveOccurred())
delegates, err := GetNetworkDelegates(kubeClient, pod, networks, tmpDir, false)
Expect(len(delegates)).To(Equal(0))
Expect(err).To(MatchError(fmt.Sprintf("GetPodNetwork: failed getting the delegate: cniConfigFromNetworkResource: err in getCNIConfigFromFile: Error loading CNI config file %s: error parsing configuration: invalid character 'a' looking for beginning of value", net2Name)))
Expect(err).To(MatchError(fmt.Sprintf("GetNetworkDelegates: failed getting the delegate: cniConfigFromNetworkResource: getCNIConfigFromFile: error loading CNI config file %s: error parsing configuration: invalid character 'a' looking for beginning of value", net2Name)))
})

It("retrieves cluster network from CRD", func() {
@@ -672,7 +672,11 @@ var _ = Describe("k8sclient operations", func() {
})

It("uses cached delegates when an error in loading from pod annotation occurs", func() {
kubeletconf, err := os.Create("/etc/kubernetes/kubelet.conf")
dir, err := ioutil.TempDir("", "multus-test")
Expect(err).NotTo(HaveOccurred())
defer os.RemoveAll(dir) // clean up

kubeletconf, err := os.Create(fmt.Sprintf("%s/kubelet.conf", dir))
kubeletconfDef := `apiVersion: v1
clusters:
- cluster:
@@ -695,15 +699,15 @@ users:
kubeletconf.Write([]byte(kubeletconfDef))
fakePod := testutils.NewFakePod("testpod", "", "net1")
conf := `{
conf := fmt.Sprintf(`{
"name":"node-cni-network",
"type":"multus",
"kubeconfig":"/etc/kubernetes/kubelet.conf",
"kubeconfig":"%s/kubelet.conf",
"delegates": [{
"type": "mynet2",
"name": "net2"
}]
}`
}`, dir)
netConf, err := types.LoadNetConf([]byte(conf))
Expect(netConf.Delegates[0].Conf.Name).To(Equal("net2"))
Expect(netConf.Delegates[0].Conf.Type).To(Equal("mynet2"))
@@ -766,7 +770,7 @@ users:
Expect(err).NotTo(HaveOccurred())
_, err = GetNetworkDelegates(kubeClient, pod, networks, tmpDir, netConf.NamespaceIsolation)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError("GetPodNetwork: namespace isolation violation: podnamespace: test / target namespace: kube-system"))
Expect(err).To(MatchError("GetNetworkDelegates: namespace isolation enabled, annotation violates permission, pod is in namespace test but refers to target namespace kube-system"))
})
@@ -30,11 +30,11 @@ func GetResourceClient() (types.ResourceClient, error) {
// If Kubelet resource API endpoint exist use that by default
// Or else fallback with checkpoint file
if hasKubeletAPIEndpoint() {
logging.Verbosef("GetResourceClient(): using Kubelet resource API endpoint")
logging.Debugf("GetResourceClient: using Kubelet resource API endpoint")
return getKubeletClient()
}

logging.Verbosef("GetResourceClient(): using Kubelet device plugin checkpoint")
logging.Debugf("GetResourceClient: using Kubelet device plugin checkpoint")
return checkpoint.GetCheckpoint()
}

@@ -46,12 +46,12 @@ func getKubeletClient() (types.ResourceClient, error) {

client, conn, err := podresources.GetClient(kubeletSocket, 10*time.Second, defaultPodResourcesMaxSize)
if err != nil {
return nil, logging.Errorf("GetResourceClient(): error getting grpc client: %v\n", err)
return nil, logging.Errorf("getKubeletClient: error getting grpc client: %v\n", err)
}
defer conn.Close()

if err := newClient.getPodResources(client); err != nil {
return nil, logging.Errorf("GetResourceClient(): error getting resource client: %v\n", err)
return nil, logging.Errorf("getKubeletClient: error ge tting pod resources from client: %v\n", err)
}

return newClient, nil
@@ -68,7 +68,7 @@ func (rc *kubeletClient) getPodResources(client podresourcesapi.PodResourcesList

resp, err := client.List(ctx, &podresourcesapi.ListPodResourcesRequest{})
if err != nil {
return logging.Errorf("getPodResources(): %v.Get(_) = _, %v", client, err)
return logging.Errorf("getPodResources: failed to list pod resources, %v.Get(_) = _, %v", client, err)
}

rc.resources = resp.PodResources
@@ -83,7 +83,7 @@ func (rc *kubeletClient) GetPodResourceMap(pod *v1.Pod) (map[string]*types.Resou
ns := pod.Namespace

if name == "" || ns == "" {
return nil, logging.Errorf("GetPodResourcesMap(): Pod name or namespace cannot be empty")
return nil, logging.Errorf("GetPodResourcesMap: Pod name or namespace cannot be empty")
}

for _, pr := range rc.resources {
@@ -106,7 +106,7 @@ func hasKubeletAPIEndpoint() bool {
// Check for kubelet resource API socket file
kubeletAPISocket := filepath.Join(defaultPodResourcesPath, defaultKubeletSocketFile)
if _, err := os.Stat(kubeletAPISocket); err != nil {
logging.Verbosef("hasKubeletAPIEndpoint(): error looking up kubelet resource api socket file: %q", err)
logging.Debugf("hasKubeletAPIEndpoint: error looking up kubelet resource api socket file: %q", err)
return false
}
return true

0 comments on commit 0a2f7b1

Please sign in to comment.
You can’t perform that action at this time.