go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/_motor/discovery/k8s/list_workloads_test.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package k8s
     5  
     6  import (
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/golang/mock/gomock"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  	"go.mondoo.com/cnquery/motor/providers"
    14  	"go.mondoo.com/cnquery/motor/providers/k8s"
    15  	appsv1 "k8s.io/api/apps/v1"
    16  	batchv1 "k8s.io/api/batch/v1"
    17  	corev1 "k8s.io/api/core/v1"
    18  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    19  )
    20  
    21  func TestListCronJobs(t *testing.T) {
    22  	mockCtrl := gomock.NewController(t)
    23  	defer mockCtrl.Finish()
    24  
    25  	p := k8s.NewMockKubernetesProvider(mockCtrl)
    26  
    27  	// Seed namespaces
    28  	nss := []corev1.Namespace{
    29  		{ObjectMeta: metav1.ObjectMeta{Name: "default"}},
    30  	}
    31  	p.EXPECT().Namespaces().Return(nss, nil)
    32  	// called for each CronJob
    33  	p.EXPECT().Runtime().Return("k8s-cluster")
    34  	p.EXPECT().Runtime().Return("k8s-cluster")
    35  
    36  	// pretend cronjob owned by deployment
    37  	parent := appsv1.Deployment{
    38  		TypeMeta: metav1.TypeMeta{
    39  			Kind:       "Deployment",
    40  			APIVersion: "apps/v1",
    41  		},
    42  		ObjectMeta: metav1.ObjectMeta{
    43  			Name:      "nginx-deployment",
    44  			Namespace: nss[0].Name,
    45  			UID:       "000",
    46  		},
    47  		Spec: appsv1.DeploymentSpec{
    48  			Template: corev1.PodTemplateSpec{
    49  				Spec: corev1.PodSpec{
    50  					Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
    51  				},
    52  			},
    53  		},
    54  	}
    55  
    56  	// Seed CronJobs
    57  	cronjobs := []*batchv1.CronJob{
    58  		{
    59  			TypeMeta: metav1.TypeMeta{
    60  				Kind:       "CronJob",
    61  				APIVersion: "batch/v1",
    62  			},
    63  			ObjectMeta: metav1.ObjectMeta{
    64  				Name:      "nginx",
    65  				Namespace: nss[0].Name,
    66  				UID:       "123",
    67  				OwnerReferences: []metav1.OwnerReference{
    68  					{
    69  						APIVersion: parent.APIVersion,
    70  						Kind:       parent.Kind,
    71  						Name:       parent.Name,
    72  						UID:        parent.UID,
    73  					},
    74  				},
    75  			},
    76  			Spec: batchv1.CronJobSpec{
    77  				Schedule: "*/1 * * * *",
    78  				JobTemplate: batchv1.JobTemplateSpec{
    79  					Spec: batchv1.JobSpec{
    80  						Template: corev1.PodTemplateSpec{
    81  							ObjectMeta: metav1.ObjectMeta{
    82  								Labels: map[string]string{
    83  									"app": "nginx",
    84  								},
    85  							},
    86  							Spec: corev1.PodSpec{
    87  								Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
    88  							},
    89  						},
    90  					},
    91  				},
    92  			},
    93  		},
    94  		{
    95  			TypeMeta: metav1.TypeMeta{
    96  				Kind:       "CronJob",
    97  				APIVersion: "batch/v1",
    98  			},
    99  			ObjectMeta: metav1.ObjectMeta{
   100  				Name:      "nginx2",
   101  				Namespace: nss[0].Name,
   102  				UID:       "456",
   103  			},
   104  			Spec: batchv1.CronJobSpec{
   105  				Schedule: "*/1 * * * *",
   106  				JobTemplate: batchv1.JobTemplateSpec{
   107  					Spec: batchv1.JobSpec{
   108  						Template: corev1.PodTemplateSpec{
   109  							ObjectMeta: metav1.ObjectMeta{
   110  								Labels: map[string]string{
   111  									"app": "nginx",
   112  								},
   113  							},
   114  							Spec: corev1.PodSpec{
   115  								Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   116  							},
   117  						},
   118  					},
   119  				},
   120  			},
   121  		},
   122  	}
   123  
   124  	p.EXPECT().CronJobs(nss[0]).Return(cronjobs, nil)
   125  
   126  	expectedAssetNames := []string{
   127  		nss[0].Name + "/" + cronjobs[0].Name,
   128  		nss[0].Name + "/" + cronjobs[1].Name,
   129  	}
   130  
   131  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
   132  
   133  	expectedAssetPlatformIds := []string{
   134  		clusterIdentifier + "/namespace/" + nss[0].Name + "/cronjobs/name/" + cronjobs[0].Name,
   135  		clusterIdentifier + "/namespace/" + nss[0].Name + "/cronjobs/name/" + cronjobs[1].Name,
   136  	}
   137  
   138  	pCfg := &providers.Config{}
   139  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
   140  	assets, err := ListCronJobs(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, make(map[string][]K8sResourceIdentifier), ownershipDir)
   141  	require.NoError(t, err)
   142  	require.Equal(t, []string{k8s.NewPlatformWorkloadId(clusterIdentifier,
   143  		strings.ToLower(parent.Kind),
   144  		parent.Namespace,
   145  		parent.Name,
   146  		"")},
   147  		ownershipDir.OwnedBy(expectedAssetPlatformIds[0]))
   148  
   149  	var assetNames []string
   150  	for _, a := range assets {
   151  		assetNames = append(assetNames, a.Name)
   152  	}
   153  
   154  	var assetPlatformIds []string
   155  	for _, a := range assets {
   156  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
   157  	}
   158  
   159  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
   160  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
   161  	assert.Equal(t, "batch/v1", assets[0].Platform.Version)
   162  	assert.Equal(t, "k8s-cronjob", assets[0].Platform.Name)
   163  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
   164  	assert.Equal(t, nss[0].Name, assets[0].Labels["k8s.mondoo.com/namespace"])
   165  }
   166  
   167  func TestListCronJobs_Filter(t *testing.T) {
   168  	mockCtrl := gomock.NewController(t)
   169  	defer mockCtrl.Finish()
   170  
   171  	p := k8s.NewMockKubernetesProvider(mockCtrl)
   172  
   173  	// called for each CronJob
   174  	p.EXPECT().Runtime().Return("k8s-cluster")
   175  
   176  	// Seed CronJobs
   177  	cronjobs := []*batchv1.CronJob{
   178  		{
   179  			TypeMeta: metav1.TypeMeta{
   180  				Kind:       "CronJob",
   181  				APIVersion: "batch/v1",
   182  			},
   183  			ObjectMeta: metav1.ObjectMeta{
   184  				Name:      "nginx",
   185  				Namespace: "default",
   186  				UID:       "123",
   187  			},
   188  			Spec: batchv1.CronJobSpec{
   189  				Schedule: "*/1 * * * *",
   190  				JobTemplate: batchv1.JobTemplateSpec{
   191  					Spec: batchv1.JobSpec{
   192  						Template: corev1.PodTemplateSpec{
   193  							ObjectMeta: metav1.ObjectMeta{
   194  								Labels: map[string]string{
   195  									"app": "nginx",
   196  								},
   197  							},
   198  							Spec: corev1.PodSpec{
   199  								Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   200  							},
   201  						},
   202  					},
   203  				},
   204  			},
   205  		},
   206  		{
   207  			TypeMeta: metav1.TypeMeta{
   208  				Kind:       "CronJob",
   209  				APIVersion: "batch/v1",
   210  			},
   211  			ObjectMeta: metav1.ObjectMeta{
   212  				Name:      "nginx2",
   213  				Namespace: "default",
   214  				UID:       "456",
   215  			},
   216  			Spec: batchv1.CronJobSpec{
   217  				Schedule: "*/1 * * * *",
   218  				JobTemplate: batchv1.JobTemplateSpec{
   219  					Spec: batchv1.JobSpec{
   220  						Template: corev1.PodTemplateSpec{
   221  							ObjectMeta: metav1.ObjectMeta{
   222  								Labels: map[string]string{
   223  									"app": "nginx",
   224  								},
   225  							},
   226  							Spec: corev1.PodSpec{
   227  								Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   228  							},
   229  						},
   230  					},
   231  				},
   232  			},
   233  		},
   234  	}
   235  
   236  	p.EXPECT().CronJob(cronjobs[0].Namespace, cronjobs[0].Name).Return(cronjobs[0], nil)
   237  
   238  	expectedAssetNames := []string{
   239  		cronjobs[0].Namespace + "/" + cronjobs[0].Name,
   240  	}
   241  
   242  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
   243  
   244  	expectedAssetPlatformIds := []string{
   245  		clusterIdentifier + "/namespace/" + cronjobs[0].Namespace + "/cronjobs/name/" + cronjobs[0].Name,
   246  	}
   247  
   248  	pCfg := &providers.Config{}
   249  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
   250  	resFilter := map[string][]K8sResourceIdentifier{
   251  		"cronjob": {
   252  			{Type: "cronjob", Name: cronjobs[0].Name, Namespace: cronjobs[0].Namespace},
   253  		},
   254  	}
   255  	assets, err := ListCronJobs(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, resFilter, ownershipDir)
   256  	require.NoError(t, err)
   257  
   258  	var assetNames []string
   259  	for _, a := range assets {
   260  		assetNames = append(assetNames, a.Name)
   261  	}
   262  
   263  	var assetPlatformIds []string
   264  	for _, a := range assets {
   265  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
   266  	}
   267  
   268  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
   269  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
   270  	assert.Equal(t, "batch/v1", assets[0].Platform.Version)
   271  	assert.Equal(t, "k8s-cronjob", assets[0].Platform.Name)
   272  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
   273  	assert.Equal(t, cronjobs[0].Namespace, assets[0].Labels["k8s.mondoo.com/namespace"])
   274  }
   275  
   276  func TestListDaemonsets(t *testing.T) {
   277  	mockCtrl := gomock.NewController(t)
   278  	defer mockCtrl.Finish()
   279  
   280  	p := k8s.NewMockKubernetesProvider(mockCtrl)
   281  
   282  	// Seed namespaces
   283  	nss := []corev1.Namespace{
   284  		{ObjectMeta: metav1.ObjectMeta{Name: "default"}},
   285  	}
   286  	p.EXPECT().Namespaces().Return(nss, nil)
   287  	// called for each DaemonSet
   288  	p.EXPECT().Runtime().Return("k8s-cluster")
   289  	p.EXPECT().Runtime().Return("k8s-cluster")
   290  
   291  	// pretend daemon set owned by deployment
   292  	parent := appsv1.Deployment{
   293  		TypeMeta: metav1.TypeMeta{
   294  			Kind:       "Deployment",
   295  			APIVersion: "apps/v1",
   296  		},
   297  		ObjectMeta: metav1.ObjectMeta{
   298  			Name:      "nginx-deployment",
   299  			Namespace: nss[0].Name,
   300  			UID:       "000",
   301  		},
   302  		Spec: appsv1.DeploymentSpec{
   303  			Template: corev1.PodTemplateSpec{
   304  				Spec: corev1.PodSpec{
   305  					Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   306  				},
   307  			},
   308  		},
   309  	}
   310  
   311  	// Seed DaemonSets
   312  	daemonsets := []*appsv1.DaemonSet{
   313  		{
   314  			TypeMeta: metav1.TypeMeta{
   315  				Kind:       "DaemonSet",
   316  				APIVersion: "apps/v1",
   317  			},
   318  			ObjectMeta: metav1.ObjectMeta{
   319  				Name:      "nginx",
   320  				Namespace: nss[0].Name,
   321  				UID:       "123",
   322  				OwnerReferences: []metav1.OwnerReference{
   323  					{
   324  						APIVersion: parent.APIVersion,
   325  						Kind:       parent.Kind,
   326  						Name:       parent.Name,
   327  						UID:        parent.UID,
   328  					},
   329  				},
   330  			},
   331  			Spec: appsv1.DaemonSetSpec{
   332  				Template: corev1.PodTemplateSpec{
   333  					Spec: corev1.PodSpec{
   334  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   335  					},
   336  				},
   337  			},
   338  		},
   339  		{
   340  			TypeMeta: metav1.TypeMeta{
   341  				Kind:       "DaemonSet",
   342  				APIVersion: "apps/v1",
   343  			},
   344  			ObjectMeta: metav1.ObjectMeta{
   345  				Name:      "nginx2",
   346  				Namespace: nss[0].Name,
   347  				UID:       "456",
   348  			},
   349  			Spec: appsv1.DaemonSetSpec{
   350  				Template: corev1.PodTemplateSpec{
   351  					Spec: corev1.PodSpec{
   352  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   353  					},
   354  				},
   355  			},
   356  		},
   357  	}
   358  
   359  	p.EXPECT().DaemonSets(nss[0]).Return(daemonsets, nil)
   360  
   361  	expectedAssetNames := []string{
   362  		nss[0].Name + "/" + daemonsets[0].Name,
   363  		nss[0].Name + "/" + daemonsets[1].Name,
   364  	}
   365  
   366  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
   367  
   368  	expectedAssetPlatformIds := []string{
   369  		clusterIdentifier + "/namespace/" + nss[0].Name + "/daemonsets/name/" + daemonsets[0].Name,
   370  		clusterIdentifier + "/namespace/" + nss[0].Name + "/daemonsets/name/" + daemonsets[1].Name,
   371  	}
   372  
   373  	pCfg := &providers.Config{}
   374  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
   375  	assets, err := ListDaemonSets(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, make(map[string][]K8sResourceIdentifier), ownershipDir)
   376  	require.NoError(t, err)
   377  	require.Equal(t, []string{k8s.NewPlatformWorkloadId(clusterIdentifier,
   378  		strings.ToLower(parent.Kind),
   379  		parent.Namespace,
   380  		parent.Name,
   381  		"")},
   382  		ownershipDir.OwnedBy(expectedAssetPlatformIds[0]))
   383  
   384  	var assetNames []string
   385  	for _, a := range assets {
   386  		assetNames = append(assetNames, a.Name)
   387  	}
   388  
   389  	var assetPlatformIds []string
   390  	for _, a := range assets {
   391  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
   392  	}
   393  
   394  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
   395  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
   396  	assert.Equal(t, "apps/v1", assets[0].Platform.Version)
   397  	assert.Equal(t, "k8s-daemonset", assets[0].Platform.Name)
   398  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
   399  	assert.Equal(t, nss[0].Name, assets[0].Labels["k8s.mondoo.com/namespace"])
   400  }
   401  
   402  func TestListDaemonsets_Filter(t *testing.T) {
   403  	mockCtrl := gomock.NewController(t)
   404  	defer mockCtrl.Finish()
   405  
   406  	p := k8s.NewMockKubernetesProvider(mockCtrl)
   407  
   408  	// called for each DaemonSet
   409  	p.EXPECT().Runtime().Return("k8s-cluster")
   410  
   411  	// Seed DaemonSets
   412  	daemonsets := []*appsv1.DaemonSet{
   413  		{
   414  			TypeMeta: metav1.TypeMeta{
   415  				Kind:       "DaemonSet",
   416  				APIVersion: "apps/v1",
   417  			},
   418  			ObjectMeta: metav1.ObjectMeta{
   419  				Name:      "nginx",
   420  				Namespace: "default",
   421  				UID:       "123",
   422  			},
   423  			Spec: appsv1.DaemonSetSpec{
   424  				Template: corev1.PodTemplateSpec{
   425  					Spec: corev1.PodSpec{
   426  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   427  					},
   428  				},
   429  			},
   430  		},
   431  		{
   432  			TypeMeta: metav1.TypeMeta{
   433  				Kind:       "DaemonSet",
   434  				APIVersion: "apps/v1",
   435  			},
   436  			ObjectMeta: metav1.ObjectMeta{
   437  				Name:      "nginx2",
   438  				Namespace: "default",
   439  				UID:       "456",
   440  			},
   441  			Spec: appsv1.DaemonSetSpec{
   442  				Template: corev1.PodTemplateSpec{
   443  					Spec: corev1.PodSpec{
   444  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   445  					},
   446  				},
   447  			},
   448  		},
   449  	}
   450  
   451  	p.EXPECT().DaemonSet(daemonsets[0].Namespace, daemonsets[0].Name).Return(daemonsets[0], nil)
   452  
   453  	expectedAssetNames := []string{
   454  		daemonsets[0].Namespace + "/" + daemonsets[0].Name,
   455  	}
   456  
   457  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
   458  
   459  	expectedAssetPlatformIds := []string{
   460  		clusterIdentifier + "/namespace/" + daemonsets[0].Namespace + "/daemonsets/name/" + daemonsets[0].Name,
   461  	}
   462  
   463  	pCfg := &providers.Config{}
   464  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
   465  	resFilter := map[string][]K8sResourceIdentifier{
   466  		"daemonset": {
   467  			{Type: "daemonset", Name: daemonsets[0].Name, Namespace: daemonsets[0].Namespace},
   468  		},
   469  	}
   470  	assets, err := ListDaemonSets(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, resFilter, ownershipDir)
   471  	require.NoError(t, err)
   472  
   473  	var assetNames []string
   474  	for _, a := range assets {
   475  		assetNames = append(assetNames, a.Name)
   476  	}
   477  
   478  	var assetPlatformIds []string
   479  	for _, a := range assets {
   480  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
   481  	}
   482  
   483  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
   484  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
   485  	assert.Equal(t, "apps/v1", assets[0].Platform.Version)
   486  	assert.Equal(t, "k8s-daemonset", assets[0].Platform.Name)
   487  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
   488  	assert.Equal(t, daemonsets[0].Namespace, assets[0].Labels["k8s.mondoo.com/namespace"])
   489  }
   490  
   491  func TestListDeployments(t *testing.T) {
   492  	mockCtrl := gomock.NewController(t)
   493  	defer mockCtrl.Finish()
   494  
   495  	p := k8s.NewMockKubernetesProvider(mockCtrl)
   496  
   497  	// Seed namespaces
   498  	nss := []corev1.Namespace{
   499  		{ObjectMeta: metav1.ObjectMeta{Name: "default"}},
   500  	}
   501  	p.EXPECT().Namespaces().Return(nss, nil)
   502  	// called for each Deployment
   503  	p.EXPECT().Runtime().Return("k8s-cluster")
   504  	p.EXPECT().Runtime().Return("k8s-cluster")
   505  
   506  	// pretend the deployment is owned by something
   507  	parent := appsv1.Deployment{
   508  		TypeMeta: metav1.TypeMeta{
   509  			Kind:       "Deployment",
   510  			APIVersion: "apps/v1",
   511  		},
   512  		ObjectMeta: metav1.ObjectMeta{
   513  			Name:      "nginx-deployment-deployment",
   514  			Namespace: nss[0].Name,
   515  			UID:       "000",
   516  		},
   517  	}
   518  
   519  	// Seed Deployments
   520  	deployments := []*appsv1.Deployment{
   521  		{
   522  			TypeMeta: metav1.TypeMeta{
   523  				Kind:       "Deployment",
   524  				APIVersion: "apps/v1",
   525  			},
   526  			ObjectMeta: metav1.ObjectMeta{
   527  				Name:      "nginx",
   528  				Namespace: nss[0].Name,
   529  				UID:       "123",
   530  				OwnerReferences: []metav1.OwnerReference{
   531  					{
   532  						APIVersion: parent.APIVersion,
   533  						Kind:       parent.Kind,
   534  						Name:       parent.Name,
   535  						UID:        parent.UID,
   536  					},
   537  				},
   538  			},
   539  			Spec: appsv1.DeploymentSpec{
   540  				Template: corev1.PodTemplateSpec{
   541  					Spec: corev1.PodSpec{
   542  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   543  					},
   544  				},
   545  			},
   546  		},
   547  		{
   548  			TypeMeta: metav1.TypeMeta{
   549  				Kind:       "Deployment",
   550  				APIVersion: "apps/v1",
   551  			},
   552  			ObjectMeta: metav1.ObjectMeta{
   553  				Name:      "nginx2",
   554  				Namespace: nss[0].Name,
   555  				UID:       "456",
   556  			},
   557  			Spec: appsv1.DeploymentSpec{
   558  				Template: corev1.PodTemplateSpec{
   559  					Spec: corev1.PodSpec{
   560  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   561  					},
   562  				},
   563  			},
   564  		},
   565  	}
   566  
   567  	p.EXPECT().Deployments(nss[0]).Return(deployments, nil)
   568  
   569  	expectedAssetNames := []string{
   570  		nss[0].Name + "/" + deployments[0].Name,
   571  		nss[0].Name + "/" + deployments[1].Name,
   572  	}
   573  
   574  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
   575  
   576  	expectedAssetPlatformIds := []string{
   577  		clusterIdentifier + "/namespace/" + nss[0].Name + "/deployments/name/" + deployments[0].Name,
   578  		clusterIdentifier + "/namespace/" + nss[0].Name + "/deployments/name/" + deployments[1].Name,
   579  	}
   580  
   581  	pCfg := &providers.Config{}
   582  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
   583  	assets, err := ListDeployments(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, make(map[string][]K8sResourceIdentifier), ownershipDir)
   584  	require.NoError(t, err)
   585  	require.Equal(t, []string{k8s.NewPlatformWorkloadId(clusterIdentifier,
   586  		strings.ToLower(parent.Kind),
   587  		parent.Namespace,
   588  		parent.Name,
   589  		"")},
   590  		ownershipDir.OwnedBy(expectedAssetPlatformIds[0]))
   591  
   592  	var assetNames []string
   593  	for _, a := range assets {
   594  		assetNames = append(assetNames, a.Name)
   595  	}
   596  
   597  	var assetPlatformIds []string
   598  	for _, a := range assets {
   599  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
   600  	}
   601  
   602  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
   603  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
   604  	assert.Equal(t, "apps/v1", assets[0].Platform.Version)
   605  	assert.Equal(t, "k8s-deployment", assets[0].Platform.Name)
   606  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
   607  	assert.Equal(t, nss[0].Name, assets[0].Labels["k8s.mondoo.com/namespace"])
   608  }
   609  
   610  func TestListDeployments_Filter(t *testing.T) {
   611  	mockCtrl := gomock.NewController(t)
   612  	defer mockCtrl.Finish()
   613  
   614  	p := k8s.NewMockKubernetesProvider(mockCtrl)
   615  
   616  	// called for each Deployment
   617  	p.EXPECT().Runtime().Return("k8s-cluster")
   618  
   619  	// Seed Deployments
   620  	deployments := []*appsv1.Deployment{
   621  		{
   622  			TypeMeta: metav1.TypeMeta{
   623  				Kind:       "Deployment",
   624  				APIVersion: "apps/v1",
   625  			},
   626  			ObjectMeta: metav1.ObjectMeta{
   627  				Name:      "nginx",
   628  				Namespace: "default",
   629  				UID:       "123",
   630  			},
   631  			Spec: appsv1.DeploymentSpec{
   632  				Template: corev1.PodTemplateSpec{
   633  					Spec: corev1.PodSpec{
   634  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   635  					},
   636  				},
   637  			},
   638  		},
   639  		{
   640  			TypeMeta: metav1.TypeMeta{
   641  				Kind:       "Deployment",
   642  				APIVersion: "apps/v1",
   643  			},
   644  			ObjectMeta: metav1.ObjectMeta{
   645  				Name:      "nginx2",
   646  				Namespace: "default",
   647  				UID:       "456",
   648  			},
   649  			Spec: appsv1.DeploymentSpec{
   650  				Template: corev1.PodTemplateSpec{
   651  					Spec: corev1.PodSpec{
   652  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   653  					},
   654  				},
   655  			},
   656  		},
   657  	}
   658  
   659  	p.EXPECT().Deployment(deployments[0].Namespace, deployments[0].Name).Return(deployments[0], nil)
   660  
   661  	expectedAssetNames := []string{
   662  		deployments[0].Namespace + "/" + deployments[0].Name,
   663  	}
   664  
   665  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
   666  
   667  	expectedAssetPlatformIds := []string{
   668  		clusterIdentifier + "/namespace/" + deployments[0].Namespace + "/deployments/name/" + deployments[0].Name,
   669  	}
   670  
   671  	pCfg := &providers.Config{}
   672  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
   673  	resFilter := map[string][]K8sResourceIdentifier{
   674  		"deployment": {
   675  			{Type: "deployment", Name: deployments[0].Name, Namespace: deployments[0].Namespace},
   676  		},
   677  	}
   678  	assets, err := ListDeployments(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, resFilter, ownershipDir)
   679  	require.NoError(t, err)
   680  
   681  	var assetNames []string
   682  	for _, a := range assets {
   683  		assetNames = append(assetNames, a.Name)
   684  	}
   685  
   686  	var assetPlatformIds []string
   687  	for _, a := range assets {
   688  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
   689  	}
   690  
   691  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
   692  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
   693  	assert.Equal(t, "apps/v1", assets[0].Platform.Version)
   694  	assert.Equal(t, "k8s-deployment", assets[0].Platform.Name)
   695  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
   696  	assert.Equal(t, deployments[0].Namespace, assets[0].Labels["k8s.mondoo.com/namespace"])
   697  }
   698  
   699  func TestListJobs(t *testing.T) {
   700  	mockCtrl := gomock.NewController(t)
   701  	defer mockCtrl.Finish()
   702  
   703  	p := k8s.NewMockKubernetesProvider(mockCtrl)
   704  
   705  	// Seed namespaces
   706  	nss := []corev1.Namespace{
   707  		{ObjectMeta: metav1.ObjectMeta{Name: "default"}},
   708  	}
   709  	p.EXPECT().Namespaces().Return(nss, nil)
   710  	// called for each Job
   711  	p.EXPECT().Runtime().Return("k8s-cluster")
   712  	p.EXPECT().Runtime().Return("k8s-cluster")
   713  
   714  	// pretend the job has a parent
   715  	parent := appsv1.ReplicaSet{
   716  		TypeMeta: metav1.TypeMeta{
   717  			Kind:       "ReplicaSet",
   718  			APIVersion: "apps/v1",
   719  		},
   720  		ObjectMeta: metav1.ObjectMeta{
   721  			Name:      "nginx-replicaset",
   722  			Namespace: nss[0].Name,
   723  			UID:       "000",
   724  		},
   725  	}
   726  
   727  	// Seed Jobs
   728  	jobs := []*batchv1.Job{
   729  		{
   730  			TypeMeta: metav1.TypeMeta{
   731  				Kind:       "Job",
   732  				APIVersion: "batch/v1",
   733  			},
   734  			ObjectMeta: metav1.ObjectMeta{
   735  				Name:      "nginx",
   736  				Namespace: nss[0].Name,
   737  				UID:       "123",
   738  				OwnerReferences: []metav1.OwnerReference{
   739  					{
   740  						APIVersion: parent.APIVersion,
   741  						Kind:       parent.Kind,
   742  						Name:       parent.Name,
   743  						UID:        parent.UID,
   744  					},
   745  				},
   746  			},
   747  			Spec: batchv1.JobSpec{
   748  				Template: corev1.PodTemplateSpec{
   749  					ObjectMeta: metav1.ObjectMeta{
   750  						Labels: map[string]string{
   751  							"app": "nginx",
   752  						},
   753  					},
   754  					Spec: corev1.PodSpec{
   755  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   756  					},
   757  				},
   758  			},
   759  		},
   760  		{
   761  			TypeMeta: metav1.TypeMeta{
   762  				Kind:       "Job",
   763  				APIVersion: "batch/v1",
   764  			},
   765  			ObjectMeta: metav1.ObjectMeta{
   766  				Name:      "nginx2",
   767  				Namespace: nss[0].Name,
   768  				UID:       "456",
   769  			},
   770  			Spec: batchv1.JobSpec{
   771  				Template: corev1.PodTemplateSpec{
   772  					ObjectMeta: metav1.ObjectMeta{
   773  						Labels: map[string]string{
   774  							"app": "nginx",
   775  						},
   776  					},
   777  					Spec: corev1.PodSpec{
   778  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   779  					},
   780  				},
   781  			},
   782  		},
   783  	}
   784  
   785  	p.EXPECT().Jobs(nss[0]).Return(jobs, nil)
   786  
   787  	expectedAssetNames := []string{
   788  		nss[0].Name + "/" + jobs[0].Name,
   789  		nss[0].Name + "/" + jobs[1].Name,
   790  	}
   791  
   792  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
   793  
   794  	expectedAssetPlatformIds := []string{
   795  		clusterIdentifier + "/namespace/" + nss[0].Name + "/jobs/name/" + jobs[0].Name,
   796  		clusterIdentifier + "/namespace/" + nss[0].Name + "/jobs/name/" + jobs[1].Name,
   797  	}
   798  
   799  	pCfg := &providers.Config{}
   800  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
   801  	ownershipDir.Add(&parent)
   802  	assets, err := ListJobs(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, make(map[string][]K8sResourceIdentifier), ownershipDir)
   803  	require.NoError(t, err)
   804  	require.Equal(t, []string{k8s.NewPlatformWorkloadId(clusterIdentifier,
   805  		strings.ToLower(parent.Kind),
   806  		parent.Namespace,
   807  		parent.Name,
   808  		"")},
   809  		ownershipDir.OwnedBy(expectedAssetPlatformIds[0]))
   810  
   811  	var assetNames []string
   812  	for _, a := range assets {
   813  		assetNames = append(assetNames, a.Name)
   814  	}
   815  
   816  	var assetPlatformIds []string
   817  	for _, a := range assets {
   818  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
   819  	}
   820  
   821  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
   822  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
   823  	assert.Equal(t, "batch/v1", assets[0].Platform.Version)
   824  	assert.Equal(t, "k8s-job", assets[0].Platform.Name)
   825  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
   826  	assert.Equal(t, nss[0].Name, assets[0].Labels["k8s.mondoo.com/namespace"])
   827  }
   828  
   829  func TestListJobs_Filter(t *testing.T) {
   830  	mockCtrl := gomock.NewController(t)
   831  	defer mockCtrl.Finish()
   832  
   833  	p := k8s.NewMockKubernetesProvider(mockCtrl)
   834  
   835  	// called for each Job
   836  	p.EXPECT().Runtime().Return("k8s-cluster")
   837  
   838  	// Seed Jobs
   839  	jobs := []*batchv1.Job{
   840  		{
   841  			TypeMeta: metav1.TypeMeta{
   842  				Kind:       "Job",
   843  				APIVersion: "batch/v1",
   844  			},
   845  			ObjectMeta: metav1.ObjectMeta{
   846  				Name:      "nginx",
   847  				Namespace: "default",
   848  				UID:       "123",
   849  			},
   850  			Spec: batchv1.JobSpec{
   851  				Template: corev1.PodTemplateSpec{
   852  					ObjectMeta: metav1.ObjectMeta{
   853  						Labels: map[string]string{
   854  							"app": "nginx",
   855  						},
   856  					},
   857  					Spec: corev1.PodSpec{
   858  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   859  					},
   860  				},
   861  			},
   862  		},
   863  		{
   864  			TypeMeta: metav1.TypeMeta{
   865  				Kind:       "Job",
   866  				APIVersion: "batch/v1",
   867  			},
   868  			ObjectMeta: metav1.ObjectMeta{
   869  				Name:      "nginx2",
   870  				Namespace: "default",
   871  				UID:       "456",
   872  			},
   873  			Spec: batchv1.JobSpec{
   874  				Template: corev1.PodTemplateSpec{
   875  					ObjectMeta: metav1.ObjectMeta{
   876  						Labels: map[string]string{
   877  							"app": "nginx",
   878  						},
   879  					},
   880  					Spec: corev1.PodSpec{
   881  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   882  					},
   883  				},
   884  			},
   885  		},
   886  	}
   887  
   888  	p.EXPECT().Job(jobs[0].Namespace, jobs[0].Name).Return(jobs[0], nil)
   889  
   890  	expectedAssetNames := []string{
   891  		jobs[0].Namespace + "/" + jobs[0].Name,
   892  	}
   893  
   894  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
   895  
   896  	expectedAssetPlatformIds := []string{
   897  		clusterIdentifier + "/namespace/" + jobs[0].Namespace + "/jobs/name/" + jobs[0].Name,
   898  	}
   899  
   900  	pCfg := &providers.Config{}
   901  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
   902  	resFilter := map[string][]K8sResourceIdentifier{
   903  		"job": {
   904  			{Type: "job", Name: jobs[0].Name, Namespace: jobs[0].Namespace},
   905  		},
   906  	}
   907  	assets, err := ListJobs(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, resFilter, ownershipDir)
   908  	require.NoError(t, err)
   909  
   910  	var assetNames []string
   911  	for _, a := range assets {
   912  		assetNames = append(assetNames, a.Name)
   913  	}
   914  
   915  	var assetPlatformIds []string
   916  	for _, a := range assets {
   917  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
   918  	}
   919  
   920  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
   921  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
   922  	assert.Equal(t, "batch/v1", assets[0].Platform.Version)
   923  	assert.Equal(t, "k8s-job", assets[0].Platform.Name)
   924  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
   925  	assert.Equal(t, jobs[0].Namespace, assets[0].Labels["k8s.mondoo.com/namespace"])
   926  }
   927  
   928  func TestListPods(t *testing.T) {
   929  	mockCtrl := gomock.NewController(t)
   930  	defer mockCtrl.Finish()
   931  
   932  	p := k8s.NewMockKubernetesProvider(mockCtrl)
   933  
   934  	// Seed namespaces
   935  	nss := []corev1.Namespace{
   936  		{ObjectMeta: metav1.ObjectMeta{Name: "default"}},
   937  	}
   938  	p.EXPECT().Namespaces().Return(nss, nil)
   939  	// called for each Pod
   940  	p.EXPECT().Runtime().Return("k8s-cluster")
   941  	p.EXPECT().Runtime().Return("k8s-cluster")
   942  
   943  	parent := appsv1.ReplicaSet{
   944  		TypeMeta: metav1.TypeMeta{
   945  			Kind:       "ReplicaSet",
   946  			APIVersion: "apps/v1",
   947  		},
   948  		ObjectMeta: metav1.ObjectMeta{
   949  			Name:      "nginx-replicaset",
   950  			Namespace: nss[0].Name,
   951  			UID:       "000",
   952  		},
   953  	}
   954  
   955  	// Seed Pods
   956  	pods := []*corev1.Pod{
   957  		{
   958  			TypeMeta: metav1.TypeMeta{
   959  				Kind:       "Pod",
   960  				APIVersion: "v1",
   961  			},
   962  			ObjectMeta: metav1.ObjectMeta{
   963  				Name:      "nginx",
   964  				Namespace: nss[0].Name,
   965  				UID:       "123",
   966  				OwnerReferences: []metav1.OwnerReference{
   967  					{
   968  						APIVersion: parent.APIVersion,
   969  						Kind:       parent.Kind,
   970  						Name:       parent.Name,
   971  						UID:        parent.UID,
   972  					},
   973  				},
   974  			},
   975  			Spec: corev1.PodSpec{
   976  				Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   977  			},
   978  		},
   979  		{
   980  			TypeMeta: metav1.TypeMeta{
   981  				Kind:       "Pod",
   982  				APIVersion: "v1",
   983  			},
   984  			ObjectMeta: metav1.ObjectMeta{
   985  				Name:      "nginx2",
   986  				Namespace: nss[0].Name,
   987  				UID:       "456",
   988  			},
   989  			Spec: corev1.PodSpec{
   990  				Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
   991  			},
   992  		},
   993  	}
   994  
   995  	p.EXPECT().Pods(nss[0]).Return(pods, nil)
   996  
   997  	expectedAssetNames := []string{
   998  		nss[0].Name + "/" + pods[0].Name,
   999  		nss[0].Name + "/" + pods[1].Name,
  1000  	}
  1001  
  1002  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
  1003  
  1004  	expectedAssetPlatformIds := []string{
  1005  		clusterIdentifier + "/namespace/" + nss[0].Name + "/pods/name/" + pods[0].Name,
  1006  		clusterIdentifier + "/namespace/" + nss[0].Name + "/pods/name/" + pods[1].Name,
  1007  	}
  1008  
  1009  	pCfg := &providers.Config{}
  1010  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
  1011  	assets, err := ListPods(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, make(map[string][]K8sResourceIdentifier), ownershipDir)
  1012  	require.NoError(t, err)
  1013  	require.Equal(t, []string{k8s.NewPlatformWorkloadId(clusterIdentifier,
  1014  		strings.ToLower(parent.Kind),
  1015  		parent.Namespace,
  1016  		parent.Name,
  1017  		"")},
  1018  		ownershipDir.OwnedBy(expectedAssetPlatformIds[0]))
  1019  	var assetNames []string
  1020  	for _, a := range assets {
  1021  		assetNames = append(assetNames, a.Name)
  1022  	}
  1023  
  1024  	var assetPlatformIds []string
  1025  	for _, a := range assets {
  1026  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
  1027  	}
  1028  
  1029  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
  1030  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
  1031  	assert.Equal(t, "v1", assets[0].Platform.Version)
  1032  	assert.Equal(t, "k8s-pod", assets[0].Platform.Name)
  1033  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
  1034  	assert.Equal(t, nss[0].Name, assets[0].Labels["k8s.mondoo.com/namespace"])
  1035  }
  1036  
  1037  func TestListPods_Filter(t *testing.T) {
  1038  	mockCtrl := gomock.NewController(t)
  1039  	defer mockCtrl.Finish()
  1040  
  1041  	p := k8s.NewMockKubernetesProvider(mockCtrl)
  1042  
  1043  	// called for each Pod
  1044  	p.EXPECT().Runtime().Return("k8s-cluster")
  1045  
  1046  	// Seed Pods
  1047  	pods := []*corev1.Pod{
  1048  		{
  1049  			TypeMeta: metav1.TypeMeta{
  1050  				Kind:       "Pod",
  1051  				APIVersion: "v1",
  1052  			},
  1053  			ObjectMeta: metav1.ObjectMeta{
  1054  				Name:      "nginx",
  1055  				Namespace: "default",
  1056  				UID:       "123",
  1057  			},
  1058  			Spec: corev1.PodSpec{
  1059  				Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
  1060  			},
  1061  		},
  1062  		{
  1063  			TypeMeta: metav1.TypeMeta{
  1064  				Kind:       "Pod",
  1065  				APIVersion: "v1",
  1066  			},
  1067  			ObjectMeta: metav1.ObjectMeta{
  1068  				Name:      "nginx2",
  1069  				Namespace: "default",
  1070  				UID:       "456",
  1071  			},
  1072  			Spec: corev1.PodSpec{
  1073  				Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
  1074  			},
  1075  		},
  1076  	}
  1077  
  1078  	p.EXPECT().Pod(pods[0].Namespace, pods[0].Name).Return(pods[0], nil)
  1079  
  1080  	expectedAssetNames := []string{
  1081  		pods[0].Namespace + "/" + pods[0].Name,
  1082  	}
  1083  
  1084  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
  1085  
  1086  	expectedAssetPlatformIds := []string{
  1087  		clusterIdentifier + "/namespace/" + pods[0].Namespace + "/pods/name/" + pods[0].Name,
  1088  	}
  1089  
  1090  	pCfg := &providers.Config{}
  1091  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
  1092  	resFilter := map[string][]K8sResourceIdentifier{
  1093  		"pod": {
  1094  			{Type: "pod", Name: pods[0].Name, Namespace: pods[0].Namespace},
  1095  		},
  1096  	}
  1097  	assets, err := ListPods(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, resFilter, ownershipDir)
  1098  	require.NoError(t, err)
  1099  	var assetNames []string
  1100  	for _, a := range assets {
  1101  		assetNames = append(assetNames, a.Name)
  1102  	}
  1103  
  1104  	var assetPlatformIds []string
  1105  	for _, a := range assets {
  1106  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
  1107  	}
  1108  
  1109  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
  1110  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
  1111  	assert.Equal(t, "v1", assets[0].Platform.Version)
  1112  	assert.Equal(t, "k8s-pod", assets[0].Platform.Name)
  1113  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
  1114  	assert.Equal(t, pods[0].Namespace, assets[0].Labels["k8s.mondoo.com/namespace"])
  1115  }
  1116  
  1117  func TestListReplicaSets(t *testing.T) {
  1118  	mockCtrl := gomock.NewController(t)
  1119  	defer mockCtrl.Finish()
  1120  
  1121  	p := k8s.NewMockKubernetesProvider(mockCtrl)
  1122  
  1123  	// Seed namespaces
  1124  	nss := []corev1.Namespace{
  1125  		{ObjectMeta: metav1.ObjectMeta{Name: "default"}},
  1126  	}
  1127  	p.EXPECT().Namespaces().Return(nss, nil)
  1128  	// called for each ReplicaSet
  1129  	p.EXPECT().Runtime().Return("k8s-cluster")
  1130  	p.EXPECT().Runtime().Return("k8s-cluster")
  1131  	parent := appsv1.Deployment{
  1132  		TypeMeta: metav1.TypeMeta{
  1133  			Kind:       "Deployment",
  1134  			APIVersion: "apps/v1",
  1135  		},
  1136  		ObjectMeta: metav1.ObjectMeta{
  1137  			Name:      "nginx-deployment",
  1138  			Namespace: nss[0].Name,
  1139  			UID:       "000",
  1140  		},
  1141  		Spec: appsv1.DeploymentSpec{
  1142  			Template: corev1.PodTemplateSpec{
  1143  				Spec: corev1.PodSpec{
  1144  					Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
  1145  				},
  1146  			},
  1147  		},
  1148  	}
  1149  	// Seed ReplicaSets
  1150  	replicaSets := []*appsv1.ReplicaSet{
  1151  		{
  1152  			TypeMeta: metav1.TypeMeta{
  1153  				Kind:       "ReplicaSet",
  1154  				APIVersion: "apps/v1",
  1155  			},
  1156  			ObjectMeta: metav1.ObjectMeta{
  1157  				Name:      "nginx",
  1158  				Namespace: nss[0].Name,
  1159  				UID:       "123",
  1160  				OwnerReferences: []metav1.OwnerReference{
  1161  					{
  1162  						APIVersion: parent.APIVersion,
  1163  						Kind:       parent.Kind,
  1164  						Name:       parent.Name,
  1165  						UID:        parent.UID,
  1166  					},
  1167  				},
  1168  			},
  1169  			Spec: appsv1.ReplicaSetSpec{
  1170  				Template: corev1.PodTemplateSpec{
  1171  					Spec: corev1.PodSpec{
  1172  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
  1173  					},
  1174  				},
  1175  			},
  1176  		},
  1177  		{
  1178  			TypeMeta: metav1.TypeMeta{
  1179  				Kind:       "ReplicaSet",
  1180  				APIVersion: "apps/v1",
  1181  			},
  1182  			ObjectMeta: metav1.ObjectMeta{
  1183  				Name:      "nginx2",
  1184  				Namespace: nss[0].Name,
  1185  				UID:       "456",
  1186  			},
  1187  			Spec: appsv1.ReplicaSetSpec{
  1188  				Template: corev1.PodTemplateSpec{
  1189  					Spec: corev1.PodSpec{
  1190  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
  1191  					},
  1192  				},
  1193  			},
  1194  		},
  1195  	}
  1196  
  1197  	p.EXPECT().ReplicaSets(nss[0]).Return(replicaSets, nil)
  1198  
  1199  	expectedAssetNames := []string{
  1200  		nss[0].Name + "/" + replicaSets[0].Name,
  1201  		nss[0].Name + "/" + replicaSets[1].Name,
  1202  	}
  1203  
  1204  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
  1205  
  1206  	expectedAssetPlatformIds := []string{
  1207  		clusterIdentifier + "/namespace/" + nss[0].Name + "/replicasets/name/" + replicaSets[0].Name,
  1208  		clusterIdentifier + "/namespace/" + nss[0].Name + "/replicasets/name/" + replicaSets[1].Name,
  1209  	}
  1210  
  1211  	pCfg := &providers.Config{}
  1212  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
  1213  	assets, err := ListReplicaSets(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, make(map[string][]K8sResourceIdentifier), ownershipDir)
  1214  	require.NoError(t, err)
  1215  	require.Equal(t, []string{k8s.NewPlatformWorkloadId(clusterIdentifier,
  1216  		strings.ToLower(parent.Kind),
  1217  		parent.Namespace,
  1218  		parent.Name,
  1219  		"")},
  1220  		ownershipDir.OwnedBy(expectedAssetPlatformIds[0]))
  1221  
  1222  	var assetNames []string
  1223  	for _, a := range assets {
  1224  		assetNames = append(assetNames, a.Name)
  1225  	}
  1226  
  1227  	var assetPlatformIds []string
  1228  	for _, a := range assets {
  1229  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
  1230  	}
  1231  
  1232  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
  1233  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
  1234  	assert.Equal(t, "apps/v1", assets[0].Platform.Version)
  1235  	assert.Equal(t, "k8s-replicaset", assets[0].Platform.Name)
  1236  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
  1237  	assert.Equal(t, nss[0].Name, assets[0].Labels["k8s.mondoo.com/namespace"])
  1238  }
  1239  
  1240  func TestListReplicaSets_Filter(t *testing.T) {
  1241  	mockCtrl := gomock.NewController(t)
  1242  	defer mockCtrl.Finish()
  1243  
  1244  	p := k8s.NewMockKubernetesProvider(mockCtrl)
  1245  
  1246  	// called for each ReplicaSet
  1247  	p.EXPECT().Runtime().Return("k8s-cluster")
  1248  
  1249  	// Seed ReplicaSets
  1250  	replicaSets := []*appsv1.ReplicaSet{
  1251  		{
  1252  			TypeMeta: metav1.TypeMeta{
  1253  				Kind:       "ReplicaSet",
  1254  				APIVersion: "apps/v1",
  1255  			},
  1256  			ObjectMeta: metav1.ObjectMeta{
  1257  				Name:      "nginx",
  1258  				Namespace: "default",
  1259  				UID:       "123",
  1260  			},
  1261  			Spec: appsv1.ReplicaSetSpec{
  1262  				Template: corev1.PodTemplateSpec{
  1263  					Spec: corev1.PodSpec{
  1264  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
  1265  					},
  1266  				},
  1267  			},
  1268  		},
  1269  		{
  1270  			TypeMeta: metav1.TypeMeta{
  1271  				Kind:       "ReplicaSet",
  1272  				APIVersion: "apps/v1",
  1273  			},
  1274  			ObjectMeta: metav1.ObjectMeta{
  1275  				Name:      "nginx2",
  1276  				Namespace: "default",
  1277  				UID:       "456",
  1278  			},
  1279  			Spec: appsv1.ReplicaSetSpec{
  1280  				Template: corev1.PodTemplateSpec{
  1281  					Spec: corev1.PodSpec{
  1282  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
  1283  					},
  1284  				},
  1285  			},
  1286  		},
  1287  	}
  1288  
  1289  	p.EXPECT().ReplicaSet(replicaSets[0].Namespace, replicaSets[0].Name).Return(replicaSets[0], nil)
  1290  
  1291  	expectedAssetNames := []string{
  1292  		replicaSets[0].Namespace + "/" + replicaSets[0].Name,
  1293  	}
  1294  
  1295  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
  1296  
  1297  	expectedAssetPlatformIds := []string{
  1298  		clusterIdentifier + "/namespace/" + replicaSets[0].Namespace + "/replicasets/name/" + replicaSets[0].Name,
  1299  	}
  1300  
  1301  	pCfg := &providers.Config{}
  1302  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
  1303  	resFilter := map[string][]K8sResourceIdentifier{
  1304  		"replicaset": {
  1305  			{Type: "replicaset", Name: replicaSets[0].Name, Namespace: replicaSets[0].Namespace},
  1306  		},
  1307  	}
  1308  	assets, err := ListReplicaSets(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, resFilter, ownershipDir)
  1309  	require.NoError(t, err)
  1310  
  1311  	var assetNames []string
  1312  	for _, a := range assets {
  1313  		assetNames = append(assetNames, a.Name)
  1314  	}
  1315  
  1316  	var assetPlatformIds []string
  1317  	for _, a := range assets {
  1318  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
  1319  	}
  1320  
  1321  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
  1322  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
  1323  	assert.Equal(t, "apps/v1", assets[0].Platform.Version)
  1324  	assert.Equal(t, "k8s-replicaset", assets[0].Platform.Name)
  1325  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
  1326  	assert.Equal(t, replicaSets[0].Namespace, assets[0].Labels["k8s.mondoo.com/namespace"])
  1327  }
  1328  
  1329  func TestListStatefulSets(t *testing.T) {
  1330  	mockCtrl := gomock.NewController(t)
  1331  	defer mockCtrl.Finish()
  1332  
  1333  	p := k8s.NewMockKubernetesProvider(mockCtrl)
  1334  
  1335  	// Seed namespaces
  1336  	nss := []corev1.Namespace{
  1337  		{ObjectMeta: metav1.ObjectMeta{Name: "default"}},
  1338  	}
  1339  	p.EXPECT().Namespaces().Return(nss, nil)
  1340  	// called for each StatefulSet
  1341  	p.EXPECT().Runtime().Return("k8s-cluster")
  1342  	p.EXPECT().Runtime().Return("k8s-cluster")
  1343  
  1344  	// pretend stateful set owned by deployment
  1345  	parent := appsv1.Deployment{
  1346  		TypeMeta: metav1.TypeMeta{
  1347  			Kind:       "Deployment",
  1348  			APIVersion: "apps/v1",
  1349  		},
  1350  		ObjectMeta: metav1.ObjectMeta{
  1351  			Name:      "nginx-deployment",
  1352  			Namespace: nss[0].Name,
  1353  			UID:       "000",
  1354  		},
  1355  		Spec: appsv1.DeploymentSpec{
  1356  			Template: corev1.PodTemplateSpec{
  1357  				Spec: corev1.PodSpec{
  1358  					Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
  1359  				},
  1360  			},
  1361  		},
  1362  	}
  1363  
  1364  	// Seed StatefulSets
  1365  	statefulsets := []*appsv1.StatefulSet{
  1366  		{
  1367  			TypeMeta: metav1.TypeMeta{
  1368  				Kind:       "StatefulSet",
  1369  				APIVersion: "apps/v1",
  1370  			},
  1371  			ObjectMeta: metav1.ObjectMeta{
  1372  				Name:      "nginx",
  1373  				Namespace: nss[0].Name,
  1374  				UID:       "123",
  1375  				OwnerReferences: []metav1.OwnerReference{
  1376  					{
  1377  						APIVersion: parent.APIVersion,
  1378  						Kind:       parent.Kind,
  1379  						Name:       parent.Name,
  1380  						UID:        parent.UID,
  1381  					},
  1382  				},
  1383  			},
  1384  			Spec: appsv1.StatefulSetSpec{
  1385  				Template: corev1.PodTemplateSpec{
  1386  					ObjectMeta: metav1.ObjectMeta{
  1387  						Labels: map[string]string{
  1388  							"app": "nginx",
  1389  						},
  1390  					},
  1391  					Spec: corev1.PodSpec{
  1392  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
  1393  					},
  1394  				},
  1395  			},
  1396  		},
  1397  		{
  1398  			TypeMeta: metav1.TypeMeta{
  1399  				Kind:       "StatefulSet",
  1400  				APIVersion: "apps/v1",
  1401  			},
  1402  			ObjectMeta: metav1.ObjectMeta{
  1403  				Name:      "nginx2",
  1404  				Namespace: nss[0].Name,
  1405  				UID:       "456",
  1406  			},
  1407  			Spec: appsv1.StatefulSetSpec{
  1408  				Template: corev1.PodTemplateSpec{
  1409  					ObjectMeta: metav1.ObjectMeta{
  1410  						Labels: map[string]string{
  1411  							"app": "nginx",
  1412  						},
  1413  					},
  1414  					Spec: corev1.PodSpec{
  1415  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
  1416  					},
  1417  				},
  1418  			},
  1419  		},
  1420  	}
  1421  
  1422  	p.EXPECT().StatefulSets(nss[0]).Return(statefulsets, nil)
  1423  
  1424  	expectedAssetNames := []string{
  1425  		nss[0].Name + "/" + statefulsets[0].Name,
  1426  		nss[0].Name + "/" + statefulsets[1].Name,
  1427  	}
  1428  
  1429  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
  1430  
  1431  	expectedAssetPlatformIds := []string{
  1432  		clusterIdentifier + "/namespace/" + nss[0].Name + "/statefulsets/name/" + statefulsets[0].Name,
  1433  		clusterIdentifier + "/namespace/" + nss[0].Name + "/statefulsets/name/" + statefulsets[1].Name,
  1434  	}
  1435  
  1436  	pCfg := &providers.Config{}
  1437  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
  1438  	assets, err := ListStatefulSets(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, make(map[string][]K8sResourceIdentifier), ownershipDir)
  1439  	require.NoError(t, err)
  1440  	require.Equal(t, []string{k8s.NewPlatformWorkloadId(clusterIdentifier,
  1441  		strings.ToLower(parent.Kind),
  1442  		parent.Namespace,
  1443  		parent.Name,
  1444  		"")},
  1445  		ownershipDir.OwnedBy(expectedAssetPlatformIds[0]))
  1446  
  1447  	var assetNames []string
  1448  	for _, a := range assets {
  1449  		assetNames = append(assetNames, a.Name)
  1450  	}
  1451  
  1452  	var assetPlatformIds []string
  1453  	for _, a := range assets {
  1454  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
  1455  	}
  1456  
  1457  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
  1458  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
  1459  	assert.Equal(t, "apps/v1", assets[0].Platform.Version)
  1460  	assert.Equal(t, "k8s-statefulset", assets[0].Platform.Name)
  1461  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
  1462  	assert.Equal(t, nss[0].Name, assets[0].Labels["k8s.mondoo.com/namespace"])
  1463  }
  1464  
  1465  func TestListStatefulSets_Filter(t *testing.T) {
  1466  	mockCtrl := gomock.NewController(t)
  1467  	defer mockCtrl.Finish()
  1468  
  1469  	p := k8s.NewMockKubernetesProvider(mockCtrl)
  1470  
  1471  	// called for each StatefulSet
  1472  	p.EXPECT().Runtime().Return("k8s-cluster")
  1473  
  1474  	// Seed StatefulSets
  1475  	statefulsets := []*appsv1.StatefulSet{
  1476  		{
  1477  			TypeMeta: metav1.TypeMeta{
  1478  				Kind:       "StatefulSet",
  1479  				APIVersion: "apps/v1",
  1480  			},
  1481  			ObjectMeta: metav1.ObjectMeta{
  1482  				Name:      "nginx",
  1483  				Namespace: "default",
  1484  				UID:       "123",
  1485  			},
  1486  			Spec: appsv1.StatefulSetSpec{
  1487  				Template: corev1.PodTemplateSpec{
  1488  					ObjectMeta: metav1.ObjectMeta{
  1489  						Labels: map[string]string{
  1490  							"app": "nginx",
  1491  						},
  1492  					},
  1493  					Spec: corev1.PodSpec{
  1494  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
  1495  					},
  1496  				},
  1497  			},
  1498  		},
  1499  		{
  1500  			TypeMeta: metav1.TypeMeta{
  1501  				Kind:       "StatefulSet",
  1502  				APIVersion: "apps/v1",
  1503  			},
  1504  			ObjectMeta: metav1.ObjectMeta{
  1505  				Name:      "nginx2",
  1506  				Namespace: "default",
  1507  				UID:       "456",
  1508  			},
  1509  			Spec: appsv1.StatefulSetSpec{
  1510  				Template: corev1.PodTemplateSpec{
  1511  					ObjectMeta: metav1.ObjectMeta{
  1512  						Labels: map[string]string{
  1513  							"app": "nginx",
  1514  						},
  1515  					},
  1516  					Spec: corev1.PodSpec{
  1517  						Containers: []corev1.Container{{Image: "nginx:1.22.0-alpine"}},
  1518  					},
  1519  				},
  1520  			},
  1521  		},
  1522  	}
  1523  
  1524  	p.EXPECT().StatefulSet(statefulsets[0].Namespace, statefulsets[0].Name).Return(statefulsets[0], nil)
  1525  
  1526  	expectedAssetNames := []string{
  1527  		statefulsets[0].Namespace + "/" + statefulsets[0].Name,
  1528  	}
  1529  
  1530  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
  1531  
  1532  	expectedAssetPlatformIds := []string{
  1533  		clusterIdentifier + "/namespace/" + statefulsets[0].Namespace + "/statefulsets/name/" + statefulsets[0].Name,
  1534  	}
  1535  
  1536  	pCfg := &providers.Config{}
  1537  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
  1538  	resFilter := map[string][]K8sResourceIdentifier{
  1539  		"statefulset": {
  1540  			{Type: "statefulset", Name: statefulsets[0].Name, Namespace: statefulsets[0].Namespace},
  1541  		},
  1542  	}
  1543  	assets, err := ListStatefulSets(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, resFilter, ownershipDir)
  1544  	require.NoError(t, err)
  1545  
  1546  	var assetNames []string
  1547  	for _, a := range assets {
  1548  		assetNames = append(assetNames, a.Name)
  1549  	}
  1550  
  1551  	var assetPlatformIds []string
  1552  	for _, a := range assets {
  1553  		assetPlatformIds = append(assetPlatformIds, a.PlatformIds[0])
  1554  	}
  1555  
  1556  	assert.ElementsMatch(t, expectedAssetNames, assetNames)
  1557  	assert.ElementsMatch(t, expectedAssetPlatformIds, assetPlatformIds)
  1558  	assert.Equal(t, "apps/v1", assets[0].Platform.Version)
  1559  	assert.Equal(t, "k8s-statefulset", assets[0].Platform.Name)
  1560  	assert.ElementsMatch(t, []string{"k8s", "k8s-workload"}, assets[0].Platform.Family)
  1561  	assert.Equal(t, statefulsets[0].Namespace, assets[0].Labels["k8s.mondoo.com/namespace"])
  1562  }
  1563  
  1564  func TestListFiltering(t *testing.T) {
  1565  	mockCtrl := gomock.NewController(t)
  1566  	defer mockCtrl.Finish()
  1567  
  1568  	p := k8s.NewMockKubernetesProvider(mockCtrl)
  1569  
  1570  	// Seed namespaces
  1571  	nss := []corev1.Namespace{
  1572  		{ObjectMeta: metav1.ObjectMeta{Name: "default"}},
  1573  		{ObjectMeta: metav1.ObjectMeta{Name: "kube-system"}},
  1574  		{ObjectMeta: metav1.ObjectMeta{Name: "kube-system-alternative"}},
  1575  	}
  1576  	p.EXPECT().Namespaces().Return(nss, nil).AnyTimes()
  1577  
  1578  	// Seed pods
  1579  	defaultNamespacePods := []*corev1.Pod{
  1580  		{
  1581  			TypeMeta:   metav1.TypeMeta{Kind: "Pod", APIVersion: "v1"},
  1582  			ObjectMeta: metav1.ObjectMeta{Name: "nginx", Namespace: nss[0].Name},
  1583  		},
  1584  		{
  1585  			TypeMeta:   metav1.TypeMeta{Kind: "Pod", APIVersion: "v1"},
  1586  			ObjectMeta: metav1.ObjectMeta{Name: "nginx2", Namespace: nss[0].Name},
  1587  		},
  1588  	}
  1589  
  1590  	kubeSystemPods := []*corev1.Pod{
  1591  		{
  1592  			TypeMeta:   metav1.TypeMeta{Kind: "Pod", APIVersion: "v1"},
  1593  			ObjectMeta: metav1.ObjectMeta{Name: "kube-proxy", Namespace: nss[1].Name},
  1594  		},
  1595  	}
  1596  
  1597  	otherNamespacePods := []*corev1.Pod{
  1598  		{
  1599  			TypeMeta:   metav1.TypeMeta{Kind: "Pod", APIVersion: "v1"},
  1600  			ObjectMeta: metav1.ObjectMeta{Name: "some-workload", Namespace: nss[2].Name},
  1601  		},
  1602  		{
  1603  			TypeMeta:   metav1.TypeMeta{Kind: "Pod", APIVersion: "v1"},
  1604  			ObjectMeta: metav1.ObjectMeta{Name: "some-workload2", Namespace: nss[2].Name},
  1605  		},
  1606  		{
  1607  			TypeMeta:   metav1.TypeMeta{Kind: "Pod", APIVersion: "v1"},
  1608  			ObjectMeta: metav1.ObjectMeta{Name: "some-workload3", Namespace: nss[2].Name},
  1609  		},
  1610  	}
  1611  	p.EXPECT().Pods(nss[0]).Return(defaultNamespacePods, nil).AnyTimes()
  1612  	p.EXPECT().Pods(nss[1]).Return(kubeSystemPods, nil).AnyTimes()
  1613  	p.EXPECT().Pods(nss[2]).Return(otherNamespacePods, nil).AnyTimes()
  1614  	p.EXPECT().Runtime().Return("k8s-cluster").AnyTimes()
  1615  
  1616  	clusterIdentifier := "//platformid.api.mondoo.app/runtime/k8s/uid/e26043bb-8669-48a2-b684-b1e132198cdc"
  1617  	ownershipDir := k8s.NewEmptyPlatformIdOwnershipDirectory(clusterIdentifier)
  1618  	pCfg := &providers.Config{}
  1619  
  1620  	// List with no filtering
  1621  	assets, err := ListPods(p, pCfg, clusterIdentifier, NamespaceFilterOpts{}, make(map[string][]K8sResourceIdentifier), ownershipDir)
  1622  	require.NoError(t, err)
  1623  	assert.Equal(t, 6, len(assets), "expected all Pods to be found when no filter specified")
  1624  
  1625  	// List only 'kube-system'
  1626  	assets, err = ListPods(p, pCfg, clusterIdentifier, NamespaceFilterOpts{include: []string{nss[1].Name}}, make(map[string][]K8sResourceIdentifier), ownershipDir)
  1627  	require.NoError(t, err)
  1628  	assert.Equal(t, 1, len(assets), "expected only 1 Pod to be returned")
  1629  
  1630  	// List 'kube-system' and 'other-namespace'
  1631  	assets, err = ListPods(p, pCfg, clusterIdentifier, NamespaceFilterOpts{include: []string{nss[1].Name, nss[2].Name}}, make(map[string][]K8sResourceIdentifier), ownershipDir)
  1632  	require.NoError(t, err)
  1633  	assert.Equal(t, 4, len(assets), "expected only 4 Pods to be returned")
  1634  
  1635  	// Exclude kube-system
  1636  	assets, err = ListPods(p, pCfg, clusterIdentifier, NamespaceFilterOpts{exclude: []string{nss[1].Name}}, make(map[string][]K8sResourceIdentifier), ownershipDir)
  1637  	require.NoError(t, err)
  1638  	assert.Equal(t, 5, len(assets), "expected only 5 Pods to be returned")
  1639  
  1640  	// Include and exclude list should behave like only include list
  1641  	assets, err = ListPods(p, pCfg, clusterIdentifier, NamespaceFilterOpts{include: []string{nss[1].Name}, exclude: []string{nss[1].Name}}, make(map[string][]K8sResourceIdentifier), ownershipDir)
  1642  	require.NoError(t, err)
  1643  	assert.Equal(t, 1, len(assets), "expected only 1 Pod to be returned")
  1644  
  1645  	// List w/glob 'kube*'
  1646  	assets, err = ListPods(p, pCfg, clusterIdentifier, NamespaceFilterOpts{include: []string{"kube*"}}, make(map[string][]K8sResourceIdentifier), ownershipDir)
  1647  	require.NoError(t, err)
  1648  	assert.Equal(t, 4, len(assets), "expected 4 Pods to be returned from matched Namespaces")
  1649  
  1650  	// List w/glob '*alt*'
  1651  	assets, err = ListPods(p, pCfg, clusterIdentifier, NamespaceFilterOpts{include: []string{"*alt*"}}, make(map[string][]K8sResourceIdentifier), ownershipDir)
  1652  	require.NoError(t, err)
  1653  	assert.Equal(t, 3, len(assets), "expected 3 Pods to be returned from matched Namespaces")
  1654  
  1655  	// Exclude w/glob '*default*'
  1656  	assets, err = ListPods(p, pCfg, clusterIdentifier, NamespaceFilterOpts{exclude: []string{"*default*"}}, make(map[string][]K8sResourceIdentifier), ownershipDir)
  1657  	require.NoError(t, err)
  1658  	assert.Equal(t, 4, len(assets), "expected 4 Pods to be returned from non-excluded Namespaces")
  1659  }