| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- package opencost
- import (
- "testing"
- "github.com/opencost/opencost/core/pkg/filter/ast"
- k8sobject "github.com/opencost/opencost/core/pkg/filter/k8sobject"
- appsv1 "k8s.io/api/apps/v1"
- batchv1 "k8s.io/api/batch/v1"
- corev1 "k8s.io/api/core/v1"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/apimachinery/pkg/runtime"
- )
- func TestK8sObjectMatcher(t *testing.T) {
- cases := []struct {
- filter string
- o runtime.Object
- expected bool
- }{
- {
- filter: `namespace:"kubecost"`,
- o: &appsv1.Deployment{
- ObjectMeta: metav1.ObjectMeta{
- Namespace: "kubecost",
- },
- },
- expected: true,
- },
- {
- filter: `namespace:"kubecost"`,
- o: &appsv1.Deployment{
- ObjectMeta: metav1.ObjectMeta{
- Namespace: "kube-system",
- },
- },
- expected: false,
- },
- {
- filter: `pod:"foo"`,
- o: &corev1.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- },
- expected: true,
- },
- {
- filter: `pod:"foo"`,
- o: &corev1.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "bar"},
- },
- expected: false,
- },
- {
- filter: `pod:"foo"`,
- o: &appsv1.Deployment{
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- },
- expected: false,
- },
- {
- filter: `controllerKind:"deployment"`,
- o: &appsv1.Deployment{},
- expected: true,
- },
- {
- filter: `controllerName:"foo"`,
- o: &appsv1.Deployment{
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- },
- expected: true,
- },
- {
- filter: `controllerKind:"statefulset"`,
- o: &appsv1.StatefulSet{},
- expected: true,
- },
- {
- filter: `controllerName:"foo"`,
- o: &appsv1.StatefulSet{
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- },
- expected: true,
- },
- {
- filter: `controllerKind:"daemonset"`,
- o: &appsv1.DaemonSet{},
- expected: true,
- },
- {
- filter: `controllerName:"foo"`,
- o: &appsv1.DaemonSet{
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- },
- expected: true,
- },
- {
- filter: `controllerKind:"cronjob"`,
- o: &batchv1.CronJob{},
- expected: true,
- },
- {
- filter: `controllerName:"foo"`,
- o: &batchv1.CronJob{
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- },
- expected: true,
- },
- {
- filter: `controllerKind:"pod"`,
- o: &corev1.Pod{},
- expected: true,
- },
- {
- filter: `controllerKind:"pod"`,
- o: &corev1.Pod{
- ObjectMeta: metav1.ObjectMeta{
- OwnerReferences: []metav1.OwnerReference{
- {}, // Having an owner reference makes this Pod "controlled"
- },
- },
- },
- expected: false,
- },
- {
- filter: `label[app]:"foo"`,
- o: &appsv1.Deployment{
- ObjectMeta: metav1.ObjectMeta{
- Labels: map[string]string{"app": "foo"},
- },
- },
- expected: true,
- },
- {
- filter: `label[app]:"foo"`,
- o: &appsv1.Deployment{
- ObjectMeta: metav1.ObjectMeta{
- Labels: map[string]string{"app": "bar"},
- },
- },
- expected: false,
- },
- {
- filter: `label[app]:"foo"`,
- o: &appsv1.Deployment{
- ObjectMeta: metav1.ObjectMeta{
- Labels: map[string]string{},
- },
- },
- expected: false,
- },
- {
- filter: `label[app]:"foo"`,
- o: &appsv1.Deployment{
- ObjectMeta: metav1.ObjectMeta{
- Labels: nil,
- },
- },
- expected: false,
- },
- {
- filter: `annotation[app]:"foo"`,
- o: &appsv1.Deployment{
- ObjectMeta: metav1.ObjectMeta{
- Annotations: map[string]string{"app": "foo"},
- },
- },
- expected: true,
- },
- {
- filter: `annotation[app]:"foo"`,
- o: &appsv1.Deployment{
- ObjectMeta: metav1.ObjectMeta{
- Annotations: map[string]string{"app": "bar"},
- },
- },
- expected: false,
- },
- {
- filter: `annotation[app]:"foo"`,
- o: &appsv1.Deployment{
- ObjectMeta: metav1.ObjectMeta{
- Annotations: map[string]string{},
- },
- },
- expected: false,
- },
- {
- filter: `annotation[app]:"foo"`,
- o: &appsv1.Deployment{
- ObjectMeta: metav1.ObjectMeta{
- Annotations: nil,
- },
- },
- expected: false,
- },
- }
- for _, c := range cases {
- t.Run(c.filter, func(t *testing.T) {
- parser := k8sobject.NewK8sObjectFilterParser()
- parsed, err := parser.Parse(c.filter)
- if err != nil {
- t.Fatalf("parsing '%s': %s", c.filter, err)
- }
- t.Logf("Parsed: %s", ast.ToPreOrderString(parsed))
- compiler := NewK8sObjectMatchCompiler()
- matcher, err := compiler.Compile(parsed)
- if err != nil {
- t.Fatalf("compiling: %s", err)
- }
- t.Logf("Compiled: %s", matcher.String())
- result := matcher.Matches(c.o)
- if result != c.expected {
- t.Errorf("Expected %t, got %t", c.expected, result)
- }
- })
- }
- }
|