github.com/alibaba/ilogtail/pkg@v0.0.0-20250526110833-c53b480d046c/helper/k8smeta/k8s_meta_link.go (about)

     1  package k8smeta
     2  
     3  import (
     4  	"strings"
     5  
     6  	app "k8s.io/api/apps/v1"
     7  	batch "k8s.io/api/batch/v1"
     8  	v1 "k8s.io/api/core/v1"
     9  	networking "k8s.io/api/networking/v1"
    10  	"k8s.io/apimachinery/pkg/labels"
    11  )
    12  
    13  type LinkGenerator struct {
    14  	metaCache map[string]MetaCache
    15  }
    16  
    17  func NewK8sMetaLinkGenerator(metaCache map[string]MetaCache) *LinkGenerator {
    18  	return &LinkGenerator{
    19  		metaCache: metaCache,
    20  	}
    21  }
    22  
    23  func (g *LinkGenerator) GenerateLinks(events []*K8sMetaEvent, linkType string) []*K8sMetaEvent {
    24  	if len(events) == 0 {
    25  		return nil
    26  	}
    27  	resourceType := events[0].Object.ResourceType
    28  	// only generate link from the src entity
    29  	if !strings.HasPrefix(linkType, resourceType) {
    30  		return nil
    31  	}
    32  	switch linkType {
    33  	case POD_NODE:
    34  		return g.getPodNodeLink(events)
    35  	case POD_DEPLOYMENT:
    36  		return g.getPodDeploymentLink(events)
    37  	case POD_REPLICASET:
    38  		return g.getPodReplicaSetLink(events)
    39  	case POD_STATEFULSET:
    40  		return g.getPodStatefulSetLink(events)
    41  	case POD_DAEMONSET:
    42  		return g.getPodDaemonSetLink(events)
    43  	case POD_JOB:
    44  		return g.getPodJobLink(events)
    45  	case JOB_CRONJOB:
    46  		return g.getJobCronJobLink(events)
    47  	case POD_PERSISENTVOLUMECLAIN:
    48  		return g.getPodPVCLink(events)
    49  	case POD_CONFIGMAP:
    50  		return g.getPodConfigMapLink(events)
    51  	case POD_SERVICE:
    52  		return g.getPodServiceLink(events)
    53  	case POD_CONTAINER:
    54  		return g.getPodContainerLink(events)
    55  	case REPLICASET_DEPLOYMENT:
    56  		return g.getReplicaSetDeploymentLink(events)
    57  	case INGRESS_SERVICE:
    58  		return g.getIngressServiceLink(events)
    59  	case POD_NAMESPACE:
    60  		return g.getPodNamespaceLink(events)
    61  	case SERVICE_NAMESPACE:
    62  		return g.getServiceNamespaceLink(events)
    63  	case DEPLOYMENT_NAMESPACE:
    64  		return g.getDeploymentNamespaceLink(events)
    65  	case DAEMONSET_NAMESPACE:
    66  		return g.getDaemonSetNamespaceLink(events)
    67  	case STATEFULSET_NAMESPACE:
    68  		return g.getStatefulsetNamespaceLink(events)
    69  	case CONFIGMAP_NAMESPACE:
    70  		return g.getConfigMapNamesapceLink(events)
    71  	case JOB_NAMESPACE:
    72  		return g.getJobNamesapceLink(events)
    73  	case CRONJOB_NAMESPACE:
    74  		return g.getCronJobNamesapceLink(events)
    75  	case PERSISTENTVOLUMECLAIM_NAMESPACE:
    76  		return g.getPVCNamesapceLink(events)
    77  	case INGRESS_NAMESPACE:
    78  		return g.getIngressNamesapceLink(events)
    79  	default:
    80  		return nil
    81  	}
    82  }
    83  
    84  func (g *LinkGenerator) getPodNodeLink(podList []*K8sMetaEvent) []*K8sMetaEvent {
    85  	nodeCache := g.metaCache[NODE]
    86  	result := make([]*K8sMetaEvent, 0)
    87  	for _, event := range podList {
    88  		pod, ok := event.Object.Raw.(*v1.Pod)
    89  		if !ok {
    90  			continue
    91  		}
    92  		nodes := nodeCache.Get([]string{pod.Spec.NodeName})
    93  		for _, node := range nodes {
    94  			for _, n := range node {
    95  				result = append(result, &K8sMetaEvent{
    96  					EventType: event.EventType,
    97  					Object: &ObjectWrapper{
    98  						ResourceType: POD_NODE,
    99  						Raw: &PodNode{
   100  							Node: n.Raw.(*v1.Node),
   101  							Pod:  pod,
   102  						},
   103  						FirstObservedTime: event.Object.FirstObservedTime,
   104  						LastObservedTime:  event.Object.LastObservedTime,
   105  					},
   106  				})
   107  			}
   108  		}
   109  	}
   110  	return result
   111  }
   112  
   113  func (g *LinkGenerator) getPodDeploymentLink(podList []*K8sMetaEvent) []*K8sMetaEvent {
   114  	result := make([]*K8sMetaEvent, 0)
   115  	for _, data := range podList {
   116  		pod, ok := data.Object.Raw.(*v1.Pod)
   117  		if !ok || len(pod.OwnerReferences) == 0 || pod.OwnerReferences[0].Kind != "ReplicaSet" {
   118  			continue
   119  		}
   120  		parentName := pod.OwnerReferences[0].Name
   121  		rsList := g.metaCache[REPLICASET].Get([]string{generateNameWithNamespaceKey(pod.Namespace, parentName)})
   122  		for _, rs := range rsList {
   123  			for _, r := range rs {
   124  				if deploymentName := r.Raw.(*app.ReplicaSet).OwnerReferences[0].Name; deploymentName != "" {
   125  					deploymentList := g.metaCache[DEPLOYMENT].Get([]string{generateNameWithNamespaceKey(pod.Namespace, deploymentName)})
   126  					for _, deployments := range deploymentList {
   127  						for _, d := range deployments {
   128  							result = append(result, &K8sMetaEvent{
   129  								EventType: data.EventType,
   130  								Object: &ObjectWrapper{
   131  									ResourceType: POD_DEPLOYMENT,
   132  									Raw: &PodDeployment{
   133  										Deployment: d.Raw.(*app.Deployment),
   134  										Pod:        pod,
   135  									},
   136  									FirstObservedTime: data.Object.FirstObservedTime,
   137  									LastObservedTime:  data.Object.LastObservedTime,
   138  								},
   139  							})
   140  						}
   141  					}
   142  				}
   143  			}
   144  		}
   145  	}
   146  	return result
   147  }
   148  
   149  func (g *LinkGenerator) getReplicaSetDeploymentLink(rsList []*K8sMetaEvent) []*K8sMetaEvent {
   150  	result := make([]*K8sMetaEvent, 0)
   151  	for _, event := range rsList {
   152  		replicaset, ok := event.Object.Raw.(*app.ReplicaSet)
   153  		if !ok || len(replicaset.OwnerReferences) == 0 {
   154  			continue
   155  		}
   156  		deploymentName := replicaset.OwnerReferences[0].Name
   157  		deployments := g.metaCache[DEPLOYMENT].Get([]string{generateNameWithNamespaceKey(replicaset.Namespace, deploymentName)})
   158  		for _, deployment := range deployments {
   159  			for _, d := range deployment {
   160  				result = append(result, &K8sMetaEvent{
   161  					EventType: event.EventType,
   162  					Object: &ObjectWrapper{
   163  						ResourceType: REPLICASET_DEPLOYMENT,
   164  						Raw: &ReplicaSetDeployment{
   165  							Deployment: d.Raw.(*app.Deployment),
   166  							ReplicaSet: replicaset,
   167  						},
   168  						FirstObservedTime: event.Object.FirstObservedTime,
   169  						LastObservedTime:  event.Object.LastObservedTime,
   170  					},
   171  				})
   172  			}
   173  		}
   174  	}
   175  	return result
   176  }
   177  
   178  func (g *LinkGenerator) getPodReplicaSetLink(podList []*K8sMetaEvent) []*K8sMetaEvent {
   179  	result := make([]*K8sMetaEvent, 0)
   180  	for _, data := range podList {
   181  		pod, ok := data.Object.Raw.(*v1.Pod)
   182  		if !ok || len(pod.OwnerReferences) == 0 || pod.OwnerReferences[0].Kind != "ReplicaSet" {
   183  			continue
   184  		}
   185  		parentName := pod.OwnerReferences[0].Name
   186  		rsList := g.metaCache[REPLICASET].Get([]string{generateNameWithNamespaceKey(pod.Namespace, parentName)})
   187  		for _, rs := range rsList {
   188  			for _, r := range rs {
   189  				result = append(result, &K8sMetaEvent{
   190  					EventType: data.EventType,
   191  					Object: &ObjectWrapper{
   192  						ResourceType: POD_REPLICASET,
   193  						Raw: &PodReplicaSet{
   194  							ReplicaSet: r.Raw.(*app.ReplicaSet),
   195  							Pod:        pod,
   196  						},
   197  						FirstObservedTime: data.Object.FirstObservedTime,
   198  						LastObservedTime:  data.Object.LastObservedTime,
   199  					},
   200  				})
   201  			}
   202  		}
   203  	}
   204  	return result
   205  }
   206  
   207  func (g *LinkGenerator) getPodStatefulSetLink(podList []*K8sMetaEvent) []*K8sMetaEvent {
   208  	result := make([]*K8sMetaEvent, 0)
   209  	for _, data := range podList {
   210  		pod, ok := data.Object.Raw.(*v1.Pod)
   211  		if !ok || len(pod.OwnerReferences) == 0 || pod.OwnerReferences[0].Kind != "StatefulSet" {
   212  			continue
   213  		}
   214  		parentName := pod.OwnerReferences[0].Name
   215  		ssList := g.metaCache[STATEFULSET].Get([]string{generateNameWithNamespaceKey(pod.Namespace, parentName)})
   216  		for _, ss := range ssList {
   217  			for _, s := range ss {
   218  				result = append(result, &K8sMetaEvent{
   219  					EventType: data.EventType,
   220  					Object: &ObjectWrapper{
   221  						ResourceType: POD_STATEFULSET,
   222  						Raw: &PodStatefulSet{
   223  							StatefulSet: s.Raw.(*app.StatefulSet),
   224  							Pod:         pod,
   225  						},
   226  						FirstObservedTime: data.Object.FirstObservedTime,
   227  						LastObservedTime:  data.Object.LastObservedTime,
   228  					},
   229  				})
   230  			}
   231  		}
   232  	}
   233  	return result
   234  }
   235  
   236  func (g *LinkGenerator) getPodDaemonSetLink(podList []*K8sMetaEvent) []*K8sMetaEvent {
   237  	result := make([]*K8sMetaEvent, 0)
   238  	for _, data := range podList {
   239  		pod, ok := data.Object.Raw.(*v1.Pod)
   240  		if !ok || len(pod.OwnerReferences) == 0 || pod.OwnerReferences[0].Kind != "DaemonSet" {
   241  			continue
   242  		}
   243  		parentName := pod.OwnerReferences[0].Name
   244  		dsList := g.metaCache[DAEMONSET].Get([]string{generateNameWithNamespaceKey(pod.Namespace, parentName)})
   245  		for _, ds := range dsList {
   246  			for _, d := range ds {
   247  				result = append(result, &K8sMetaEvent{
   248  					EventType: data.EventType,
   249  					Object: &ObjectWrapper{
   250  						ResourceType: POD_DAEMONSET,
   251  						Raw: &PodDaemonSet{
   252  							DaemonSet: d.Raw.(*app.DaemonSet),
   253  							Pod:       pod,
   254  						},
   255  						FirstObservedTime: data.Object.FirstObservedTime,
   256  						LastObservedTime:  data.Object.LastObservedTime,
   257  					},
   258  				})
   259  			}
   260  		}
   261  	}
   262  	return result
   263  }
   264  
   265  func (g *LinkGenerator) getPodJobLink(podList []*K8sMetaEvent) []*K8sMetaEvent {
   266  	result := make([]*K8sMetaEvent, 0)
   267  	for _, data := range podList {
   268  		pod, ok := data.Object.Raw.(*v1.Pod)
   269  		if !ok || len(pod.OwnerReferences) == 0 || pod.OwnerReferences[0].Kind != "Job" {
   270  			continue
   271  		}
   272  		parentName := pod.OwnerReferences[0].Name
   273  		jobList := g.metaCache[JOB].Get([]string{generateNameWithNamespaceKey(pod.Namespace, parentName)})
   274  		for _, job := range jobList {
   275  			for _, j := range job {
   276  				result = append(result, &K8sMetaEvent{
   277  					EventType: data.EventType,
   278  					Object: &ObjectWrapper{
   279  						ResourceType: POD_JOB,
   280  						Raw: &PodJob{
   281  							Job: j.Raw.(*batch.Job),
   282  							Pod: pod,
   283  						},
   284  						FirstObservedTime: data.Object.FirstObservedTime,
   285  						LastObservedTime:  data.Object.LastObservedTime,
   286  					},
   287  				})
   288  			}
   289  		}
   290  	}
   291  	return result
   292  }
   293  
   294  func (g *LinkGenerator) getJobCronJobLink(jobList []*K8sMetaEvent) []*K8sMetaEvent {
   295  	result := make([]*K8sMetaEvent, 0)
   296  	for _, data := range jobList {
   297  		job, ok := data.Object.Raw.(*batch.Job)
   298  		if !ok || len(job.OwnerReferences) == 0 {
   299  			continue
   300  		}
   301  		cronJobName := job.OwnerReferences[0].Name
   302  		cronJobList := g.metaCache[CRONJOB].Get([]string{generateNameWithNamespaceKey(job.Namespace, cronJobName)})
   303  		for _, cj := range cronJobList {
   304  			for _, c := range cj {
   305  				result = append(result, &K8sMetaEvent{
   306  					EventType: data.EventType,
   307  					Object: &ObjectWrapper{
   308  						ResourceType: JOB_CRONJOB,
   309  						Raw: &JobCronJob{
   310  							CronJob: c.Raw.(*batch.CronJob),
   311  							Job:     job,
   312  						},
   313  						FirstObservedTime: data.Object.FirstObservedTime,
   314  						LastObservedTime:  data.Object.LastObservedTime,
   315  					},
   316  				})
   317  			}
   318  		}
   319  	}
   320  	return result
   321  }
   322  
   323  func (g *LinkGenerator) getPodPVCLink(podList []*K8sMetaEvent) []*K8sMetaEvent {
   324  	result := make([]*K8sMetaEvent, 0)
   325  	for _, data := range podList {
   326  		pod, ok := data.Object.Raw.(*v1.Pod)
   327  		if !ok {
   328  			continue
   329  		}
   330  		for _, volume := range pod.Spec.Volumes {
   331  			if volume.PersistentVolumeClaim != nil {
   332  				pvcName := volume.PersistentVolumeClaim.ClaimName
   333  				pvcList := g.metaCache[PERSISTENTVOLUMECLAIM].Get([]string{generateNameWithNamespaceKey(pod.Namespace, pvcName)})
   334  				for _, pvc := range pvcList {
   335  					for _, p := range pvc {
   336  						result = append(result, &K8sMetaEvent{
   337  							EventType: data.EventType,
   338  							Object: &ObjectWrapper{
   339  								ResourceType: POD_PERSISENTVOLUMECLAIN,
   340  								Raw: &PodPersistentVolumeClaim{
   341  									Pod:                   pod,
   342  									PersistentVolumeClaim: p.Raw.(*v1.PersistentVolumeClaim),
   343  								},
   344  								FirstObservedTime: data.Object.FirstObservedTime,
   345  								LastObservedTime:  data.Object.LastObservedTime,
   346  							},
   347  						})
   348  					}
   349  				}
   350  			}
   351  		}
   352  	}
   353  	return result
   354  }
   355  
   356  func (g *LinkGenerator) getPodConfigMapLink(podList []*K8sMetaEvent) []*K8sMetaEvent {
   357  	result := make([]*K8sMetaEvent, 0)
   358  	for _, data := range podList {
   359  		pod, ok := data.Object.Raw.(*v1.Pod)
   360  		if !ok {
   361  			continue
   362  		}
   363  		for _, volume := range pod.Spec.Volumes {
   364  			if volume.ConfigMap != nil {
   365  				cmName := volume.ConfigMap.Name
   366  				cmList := g.metaCache[CONFIGMAP].Get([]string{generateNameWithNamespaceKey(pod.Namespace, cmName)})
   367  				for _, cm := range cmList {
   368  					for _, c := range cm {
   369  						result = append(result, &K8sMetaEvent{
   370  							EventType: data.EventType,
   371  							Object: &ObjectWrapper{
   372  								ResourceType: POD_CONFIGMAP,
   373  								Raw: &PodConfigMap{
   374  									Pod:       pod,
   375  									ConfigMap: c.Raw.(*v1.ConfigMap),
   376  								},
   377  								FirstObservedTime: data.Object.FirstObservedTime,
   378  								LastObservedTime:  data.Object.LastObservedTime,
   379  							},
   380  						})
   381  					}
   382  				}
   383  			}
   384  		}
   385  	}
   386  	return result
   387  }
   388  
   389  func (g *LinkGenerator) getPodServiceLink(podList []*K8sMetaEvent) []*K8sMetaEvent {
   390  	serviceList := g.metaCache[SERVICE].List()
   391  	result := make([]*K8sMetaEvent, 0)
   392  	matchers := make(map[string]labelMatchers)
   393  	for _, data := range serviceList {
   394  		service, ok := data.Raw.(*v1.Service)
   395  		if !ok {
   396  			continue
   397  		}
   398  
   399  		_, ok = matchers[service.Namespace]
   400  		lm := newLabelMatcher(data.Raw, labels.SelectorFromSet(service.Spec.Selector))
   401  		if !ok {
   402  			matchers[service.Namespace] = []*labelMatcher{lm}
   403  		} else {
   404  			matchers[service.Namespace] = append(matchers[service.Namespace], lm)
   405  		}
   406  	}
   407  
   408  	for _, data := range podList {
   409  		pod, ok := data.Object.Raw.(*v1.Pod)
   410  		if !ok {
   411  			continue
   412  		}
   413  		nsSelectors, ok := matchers[pod.Namespace]
   414  		if !ok {
   415  			continue
   416  		}
   417  		set := labels.Set(pod.Labels)
   418  		for _, s := range nsSelectors {
   419  			if !s.selector.Empty() && s.selector.Matches(set) {
   420  				result = append(result, &K8sMetaEvent{
   421  					EventType: data.EventType,
   422  					Object: &ObjectWrapper{
   423  						ResourceType: POD_SERVICE,
   424  						Raw: &PodService{
   425  							Pod:     pod,
   426  							Service: s.obj.(*v1.Service),
   427  						},
   428  						FirstObservedTime: data.Object.FirstObservedTime,
   429  						LastObservedTime:  data.Object.LastObservedTime,
   430  					},
   431  				})
   432  			}
   433  		}
   434  	}
   435  	return result
   436  }
   437  
   438  func (g *LinkGenerator) getPodContainerLink(podList []*K8sMetaEvent) []*K8sMetaEvent {
   439  	result := make([]*K8sMetaEvent, 0)
   440  	for _, data := range podList {
   441  		pod, ok := data.Object.Raw.(*v1.Pod)
   442  		if !ok {
   443  			continue
   444  		}
   445  		for i := range pod.Spec.Containers {
   446  			result = append(result, &K8sMetaEvent{
   447  				EventType: data.EventType,
   448  				Object: &ObjectWrapper{
   449  					ResourceType: POD_CONTAINER,
   450  					Raw: &PodContainer{
   451  						Pod:       pod,
   452  						Container: &pod.Spec.Containers[i],
   453  					},
   454  					FirstObservedTime: data.Object.FirstObservedTime,
   455  					LastObservedTime:  data.Object.LastObservedTime,
   456  				},
   457  			})
   458  		}
   459  	}
   460  	return result
   461  }
   462  
   463  func (g *LinkGenerator) getIngressServiceLink(ingressList []*K8sMetaEvent) []*K8sMetaEvent {
   464  	result := make([]*K8sMetaEvent, 0)
   465  	for _, data := range ingressList {
   466  		ingress, ok := data.Object.Raw.(*networking.Ingress)
   467  		if !ok {
   468  			continue
   469  		}
   470  		serviceNameSet := make(map[string]struct{}, 0)
   471  		for _, rule := range ingress.Spec.Rules {
   472  			for _, path := range rule.HTTP.Paths {
   473  				serviceNameSet[path.Backend.Service.Name] = struct{}{}
   474  			}
   475  		}
   476  		serviceNameList := make([]string, 0, len(serviceNameSet))
   477  		for name := range serviceNameSet {
   478  			serviceNameList = append(serviceNameList, generateNameWithNamespaceKey(ingress.Namespace, name))
   479  		}
   480  		serviceList := g.metaCache[SERVICE].Get(serviceNameList)
   481  		for _, service := range serviceList {
   482  			for _, s := range service {
   483  				result = append(result, &K8sMetaEvent{
   484  					EventType: data.EventType,
   485  					Object: &ObjectWrapper{
   486  						ResourceType: INGRESS_SERVICE,
   487  						Raw: &IngressService{
   488  							Ingress: ingress,
   489  							Service: s.Raw.(*v1.Service),
   490  						},
   491  						FirstObservedTime: data.Object.FirstObservedTime,
   492  						LastObservedTime:  data.Object.LastObservedTime,
   493  					},
   494  				})
   495  			}
   496  		}
   497  	}
   498  	return result
   499  }
   500  
   501  func (g *LinkGenerator) getPodNamespaceLink(podList []*K8sMetaEvent) []*K8sMetaEvent {
   502  	result := make([]*K8sMetaEvent, 0)
   503  	for _, data := range podList {
   504  		pod, ok := data.Object.Raw.(*v1.Pod)
   505  		if !ok {
   506  			continue
   507  		}
   508  		nsList := g.metaCache[NAMESPACE].Get([]string{generateNameWithNamespaceKey("", pod.Namespace)})
   509  		for _, ns := range nsList {
   510  			for _, n := range ns {
   511  				result = append(result, &K8sMetaEvent{
   512  					EventType: data.EventType,
   513  					Object: &ObjectWrapper{
   514  						ResourceType: POD_NAMESPACE,
   515  						Raw: &PodNamespace{
   516  							Pod:       pod,
   517  							Namespace: n.Raw.(*v1.Namespace),
   518  						},
   519  						FirstObservedTime: data.Object.FirstObservedTime,
   520  						LastObservedTime:  data.Object.LastObservedTime,
   521  					},
   522  				})
   523  			}
   524  		}
   525  	}
   526  	return result
   527  }
   528  
   529  func (g *LinkGenerator) getServiceNamespaceLink(serviceList []*K8sMetaEvent) []*K8sMetaEvent {
   530  	result := make([]*K8sMetaEvent, 0)
   531  	for _, data := range serviceList {
   532  		service, ok := data.Object.Raw.(*v1.Service)
   533  		if !ok {
   534  			continue
   535  		}
   536  		nsList := g.metaCache[NAMESPACE].Get([]string{generateNameWithNamespaceKey("", service.Namespace)})
   537  		for _, ns := range nsList {
   538  			for _, n := range ns {
   539  				result = append(result, &K8sMetaEvent{
   540  					EventType: data.EventType,
   541  					Object: &ObjectWrapper{
   542  						ResourceType: SERVICE_NAMESPACE,
   543  						Raw: &ServiceNamespace{
   544  							Service:   service,
   545  							Namespace: n.Raw.(*v1.Namespace),
   546  						},
   547  						FirstObservedTime: data.Object.FirstObservedTime,
   548  						LastObservedTime:  data.Object.LastObservedTime,
   549  					},
   550  				})
   551  			}
   552  		}
   553  	}
   554  	return result
   555  }
   556  
   557  func (g *LinkGenerator) getDeploymentNamespaceLink(deploymentList []*K8sMetaEvent) []*K8sMetaEvent {
   558  	result := make([]*K8sMetaEvent, 0)
   559  	for _, data := range deploymentList {
   560  		deployment, ok := data.Object.Raw.(*app.Deployment)
   561  		if !ok {
   562  			continue
   563  		}
   564  		nsList := g.metaCache[NAMESPACE].Get([]string{generateNameWithNamespaceKey("", deployment.Namespace)})
   565  		for _, ns := range nsList {
   566  			for _, n := range ns {
   567  				result = append(result, &K8sMetaEvent{
   568  					EventType: data.EventType,
   569  					Object: &ObjectWrapper{
   570  						ResourceType: DEPLOYMENT_NAMESPACE,
   571  						Raw: &DeploymentNamespace{
   572  							Deployment: deployment,
   573  							Namespace:  n.Raw.(*v1.Namespace),
   574  						},
   575  						FirstObservedTime: data.Object.FirstObservedTime,
   576  						LastObservedTime:  data.Object.LastObservedTime,
   577  					},
   578  				})
   579  			}
   580  		}
   581  	}
   582  	return result
   583  }
   584  func (g *LinkGenerator) getDaemonSetNamespaceLink(daemonsetList []*K8sMetaEvent) []*K8sMetaEvent {
   585  	result := make([]*K8sMetaEvent, 0)
   586  	for _, data := range daemonsetList {
   587  		daemonset, ok := data.Object.Raw.(*app.DaemonSet)
   588  		if !ok {
   589  			continue
   590  		}
   591  		nsList := g.metaCache[NAMESPACE].Get([]string{generateNameWithNamespaceKey("", daemonset.Namespace)})
   592  		for _, ns := range nsList {
   593  			for _, n := range ns {
   594  				result = append(result, &K8sMetaEvent{
   595  					EventType: data.EventType,
   596  					Object: &ObjectWrapper{
   597  						ResourceType: DAEMONSET_NAMESPACE,
   598  						Raw: &DaemonSetNamespace{
   599  							DaemonSet: daemonset,
   600  							Namespace: n.Raw.(*v1.Namespace),
   601  						},
   602  						FirstObservedTime: data.Object.FirstObservedTime,
   603  						LastObservedTime:  data.Object.LastObservedTime,
   604  					},
   605  				})
   606  			}
   607  		}
   608  	}
   609  	return result
   610  }
   611  func (g *LinkGenerator) getStatefulsetNamespaceLink(statefulsetList []*K8sMetaEvent) []*K8sMetaEvent {
   612  	result := make([]*K8sMetaEvent, 0)
   613  	for _, data := range statefulsetList {
   614  		statefulset, ok := data.Object.Raw.(*app.StatefulSet)
   615  		if !ok {
   616  			continue
   617  		}
   618  		nsList := g.metaCache[NAMESPACE].Get([]string{generateNameWithNamespaceKey("", statefulset.Namespace)})
   619  		for _, ns := range nsList {
   620  			for _, n := range ns {
   621  				result = append(result, &K8sMetaEvent{
   622  					EventType: data.EventType,
   623  					Object: &ObjectWrapper{
   624  						ResourceType: STATEFULSET_NAMESPACE,
   625  						Raw: &StatefulSetNamespace{
   626  							StatefulSet: statefulset,
   627  							Namespace:   n.Raw.(*v1.Namespace),
   628  						},
   629  						FirstObservedTime: data.Object.FirstObservedTime,
   630  						LastObservedTime:  data.Object.LastObservedTime,
   631  					},
   632  				})
   633  			}
   634  		}
   635  	}
   636  	return result
   637  }
   638  func (g *LinkGenerator) getConfigMapNamesapceLink(configMapList []*K8sMetaEvent) []*K8sMetaEvent {
   639  	result := make([]*K8sMetaEvent, 0)
   640  	for _, data := range configMapList {
   641  		configmap, ok := data.Object.Raw.(*v1.ConfigMap)
   642  		if !ok {
   643  			continue
   644  		}
   645  		nsList := g.metaCache[NAMESPACE].Get([]string{generateNameWithNamespaceKey("", configmap.Namespace)})
   646  		for _, ns := range nsList {
   647  			for _, n := range ns {
   648  				result = append(result, &K8sMetaEvent{
   649  					EventType: data.EventType,
   650  					Object: &ObjectWrapper{
   651  						ResourceType: CONFIGMAP_NAMESPACE,
   652  						Raw: &ConfigMapNamespace{
   653  							ConfigMap: configmap,
   654  							Namespace: n.Raw.(*v1.Namespace),
   655  						},
   656  						FirstObservedTime: data.Object.FirstObservedTime,
   657  						LastObservedTime:  data.Object.LastObservedTime,
   658  					},
   659  				})
   660  			}
   661  		}
   662  	}
   663  	return result
   664  }
   665  func (g *LinkGenerator) getJobNamesapceLink(jobList []*K8sMetaEvent) []*K8sMetaEvent {
   666  	result := make([]*K8sMetaEvent, 0)
   667  	for _, data := range jobList {
   668  		job, ok := data.Object.Raw.(*batch.Job)
   669  		if !ok {
   670  			continue
   671  		}
   672  		nsList := g.metaCache[NAMESPACE].Get([]string{generateNameWithNamespaceKey("", job.Namespace)})
   673  		for _, ns := range nsList {
   674  			for _, n := range ns {
   675  				result = append(result, &K8sMetaEvent{
   676  					EventType: data.EventType,
   677  					Object: &ObjectWrapper{
   678  						ResourceType: JOB_NAMESPACE,
   679  						Raw: &JobNamespace{
   680  							Job:       job,
   681  							Namespace: n.Raw.(*v1.Namespace),
   682  						},
   683  						FirstObservedTime: data.Object.FirstObservedTime,
   684  						LastObservedTime:  data.Object.LastObservedTime,
   685  					},
   686  				})
   687  			}
   688  		}
   689  	}
   690  	return result
   691  }
   692  func (g *LinkGenerator) getCronJobNamesapceLink(jobList []*K8sMetaEvent) []*K8sMetaEvent {
   693  	result := make([]*K8sMetaEvent, 0)
   694  	for _, data := range jobList {
   695  		job, ok := data.Object.Raw.(*batch.CronJob)
   696  		if !ok {
   697  			continue
   698  		}
   699  		nsList := g.metaCache[NAMESPACE].Get([]string{generateNameWithNamespaceKey("", job.Namespace)})
   700  		for _, ns := range nsList {
   701  			for _, n := range ns {
   702  				result = append(result, &K8sMetaEvent{
   703  					EventType: data.EventType,
   704  					Object: &ObjectWrapper{
   705  						ResourceType: CRONJOB_NAMESPACE,
   706  						Raw: &CronJobNamespace{
   707  							CronJob:   job,
   708  							Namespace: n.Raw.(*v1.Namespace),
   709  						},
   710  						FirstObservedTime: data.Object.FirstObservedTime,
   711  						LastObservedTime:  data.Object.LastObservedTime,
   712  					},
   713  				})
   714  			}
   715  		}
   716  	}
   717  	return result
   718  }
   719  
   720  func (g *LinkGenerator) getPVCNamesapceLink(pvcList []*K8sMetaEvent) []*K8sMetaEvent {
   721  	result := make([]*K8sMetaEvent, 0)
   722  	for _, data := range pvcList {
   723  		pvc, ok := data.Object.Raw.(*v1.PersistentVolumeClaim)
   724  		if !ok {
   725  			continue
   726  		}
   727  		nsList := g.metaCache[NAMESPACE].Get([]string{generateNameWithNamespaceKey("", pvc.Namespace)})
   728  		for _, ns := range nsList {
   729  			for _, n := range ns {
   730  				result = append(result, &K8sMetaEvent{
   731  					EventType: data.EventType,
   732  					Object: &ObjectWrapper{
   733  						ResourceType: PERSISTENTVOLUMECLAIM_NAMESPACE,
   734  						Raw: &PersistentVolumeClaimNamespace{
   735  							PersistentVolumeClaim: pvc,
   736  							Namespace:             n.Raw.(*v1.Namespace),
   737  						},
   738  						FirstObservedTime: data.Object.FirstObservedTime,
   739  						LastObservedTime:  data.Object.LastObservedTime,
   740  					},
   741  				})
   742  			}
   743  		}
   744  	}
   745  	return result
   746  }
   747  
   748  func (g *LinkGenerator) getIngressNamesapceLink(ingressList []*K8sMetaEvent) []*K8sMetaEvent {
   749  	result := make([]*K8sMetaEvent, 0)
   750  	for _, data := range ingressList {
   751  		ingress, ok := data.Object.Raw.(*networking.Ingress)
   752  		if !ok {
   753  			continue
   754  		}
   755  		nsList := g.metaCache[NAMESPACE].Get([]string{generateNameWithNamespaceKey("", ingress.Namespace)})
   756  		for _, ns := range nsList {
   757  			for _, n := range ns {
   758  				result = append(result, &K8sMetaEvent{
   759  					EventType: data.EventType,
   760  					Object: &ObjectWrapper{
   761  						ResourceType: INGRESS_NAMESPACE,
   762  						Raw: &IngressNamespace{
   763  							Ingress:   ingress,
   764  							Namespace: n.Raw.(*v1.Namespace),
   765  						},
   766  						FirstObservedTime: data.Object.FirstObservedTime,
   767  						LastObservedTime:  data.Object.LastObservedTime,
   768  					},
   769  				})
   770  			}
   771  		}
   772  	}
   773  	return result
   774  }