github.com/argoproj/argo-events@v1.9.1/eventsources/sources/resource/start_test.go (about)

     1  /*
     2  Copyright 2018 BlackRock, Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package resource
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/smartystreets/goconvey/convey"
    27  	corev1 "k8s.io/api/core/v1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    30  	"k8s.io/apimachinery/pkg/labels"
    31  	"k8s.io/client-go/kubernetes/fake"
    32  
    33  	"github.com/argoproj/argo-events/common/logging"
    34  	"github.com/argoproj/argo-events/pkg/apis/eventsource/v1alpha1"
    35  )
    36  
    37  func TestFilter(t *testing.T) {
    38  	convey.Convey("Given a resource object, apply filter on it", t, func() {
    39  		resourceEventSource := &v1alpha1.ResourceEventSource{
    40  			Namespace: "fake",
    41  			GroupVersionResource: metav1.GroupVersionResource{
    42  				Group:    "",
    43  				Resource: "pods",
    44  				Version:  "v1",
    45  			},
    46  			Filter: &v1alpha1.ResourceFilter{
    47  				Labels: []v1alpha1.Selector{
    48  					{
    49  						Key:       "workflows.argoproj.io/phase",
    50  						Operation: "==",
    51  						Value:     "Succeeded",
    52  					},
    53  					{
    54  						Key:       "name",
    55  						Operation: "==",
    56  						Value:     "my-workflow",
    57  					},
    58  				},
    59  				Fields: []v1alpha1.Selector{
    60  					{
    61  						Key:       "metadata.name",
    62  						Operation: "==",
    63  						Value:     "fak*",
    64  					},
    65  					{
    66  						Key:       "status.phase",
    67  						Operation: "!=",
    68  						Value:     "Error",
    69  					},
    70  					{
    71  						Key:       "spec.serviceAccountName",
    72  						Operation: "=",
    73  						Value:     "test*",
    74  					},
    75  				},
    76  			},
    77  		}
    78  		pod := &corev1.Pod{
    79  			ObjectMeta: metav1.ObjectMeta{
    80  				Name:      "fake",
    81  				Namespace: "fake",
    82  				Labels: map[string]string{
    83  					"workflows.argoproj.io/phase": "Succeeded",
    84  					"name":                        "my-workflow",
    85  				},
    86  			},
    87  			Spec: corev1.PodSpec{
    88  				ServiceAccountName: "test-sa",
    89  			},
    90  			Status: corev1.PodStatus{
    91  				Phase: "Running",
    92  			},
    93  		}
    94  		pod, err := fake.NewSimpleClientset().CoreV1().Pods("fake").Create(context.TODO(), pod, metav1.CreateOptions{})
    95  		convey.So(err, convey.ShouldBeNil)
    96  
    97  		outmap := make(map[string]interface{})
    98  		jsonData, err := json.Marshal(pod)
    99  		convey.So(err, convey.ShouldBeNil)
   100  		err = json.Unmarshal(jsonData, &outmap)
   101  		convey.So(err, convey.ShouldBeNil)
   102  
   103  		pass := passFilters(&InformerEvent{
   104  			Obj:  &unstructured.Unstructured{Object: outmap},
   105  			Type: "ADD",
   106  		}, resourceEventSource.Filter, time.Now(), logging.NewArgoEventsLogger())
   107  		convey.So(pass, convey.ShouldBeTrue)
   108  	})
   109  }
   110  
   111  func TestLabelSelector(t *testing.T) {
   112  	// Test equality operators =, == and in
   113  	for _, op := range []string{"==", "=", "in"} {
   114  		t.Run(fmt.Sprintf("Test operator %v", op), func(t *testing.T) {
   115  			r, err := LabelSelector([]v1alpha1.Selector{{
   116  				Key:       "key",
   117  				Operation: op,
   118  				Value:     "1",
   119  			}})
   120  			if err != nil {
   121  				t.Fatal(err)
   122  			}
   123  			validL := &labels.Set{"key": "1"}
   124  			if !r.Matches(validL) {
   125  				t.Errorf("didnot match %v", validL)
   126  			}
   127  			invalidL := &labels.Set{"key": "2"}
   128  			if r.Matches(invalidL) {
   129  				t.Errorf("matched %v", invalidL)
   130  			}
   131  		})
   132  	}
   133  	// Test inequality operators != and notin
   134  	for _, op := range []string{"!=", "notin"} {
   135  		t.Run(fmt.Sprintf("Test operator %v", op), func(t *testing.T) {
   136  			r, err := LabelSelector([]v1alpha1.Selector{{
   137  				Key:       "key",
   138  				Operation: op,
   139  				Value:     "1",
   140  			}})
   141  			if err != nil {
   142  				t.Fatal(err)
   143  			}
   144  			validL := &labels.Set{"key": "2"}
   145  			if !r.Matches(validL) {
   146  				t.Errorf("didnot match %v", validL)
   147  			}
   148  			invalidL := &labels.Set{"key": "1"}
   149  			if r.Matches(invalidL) {
   150  				t.Errorf("matched %v", invalidL)
   151  			}
   152  		})
   153  	}
   154  	// Test greater than operator
   155  	t.Run("Test operator gt", func(t *testing.T) {
   156  		r, err := LabelSelector([]v1alpha1.Selector{{
   157  			Key:       "key",
   158  			Operation: "gt",
   159  			Value:     "1",
   160  		}})
   161  		if err != nil {
   162  			t.Fatal(err)
   163  		}
   164  		validL := &labels.Set{"key": "2"}
   165  		if !r.Matches(validL) {
   166  			t.Errorf("didnot match %v", validL)
   167  		}
   168  		invalidL := &labels.Set{"key": "1"}
   169  		if r.Matches(invalidL) {
   170  			t.Errorf("matched %v", invalidL)
   171  		}
   172  	})
   173  	// Test lower than operator
   174  	t.Run("Test operator lt", func(t *testing.T) {
   175  		r, err := LabelSelector([]v1alpha1.Selector{{
   176  			Key:       "key",
   177  			Operation: "lt",
   178  			Value:     "2",
   179  		}})
   180  		if err != nil {
   181  			t.Fatal(err)
   182  		}
   183  		validL := &labels.Set{"key": "1"}
   184  		if !r.Matches(validL) {
   185  			t.Errorf("didnot match %v", validL)
   186  		}
   187  		invalidL := &labels.Set{"key": "2"}
   188  		if r.Matches(invalidL) {
   189  			t.Errorf("matched %v", invalidL)
   190  		}
   191  	})
   192  	// Test exists operator
   193  	t.Run("Test operator exists", func(t *testing.T) {
   194  		r, err := LabelSelector([]v1alpha1.Selector{{
   195  			Key:       "key",
   196  			Operation: "exists",
   197  		}})
   198  		if err != nil {
   199  			t.Fatal(err)
   200  		}
   201  		validL := &labels.Set{"key": "something"}
   202  		if !r.Matches(validL) {
   203  			t.Errorf("didnot match %v", validL)
   204  		}
   205  		invalidL := &labels.Set{"notkey": "something"}
   206  		if r.Matches(invalidL) {
   207  			t.Errorf("matched %v", invalidL)
   208  		}
   209  	})
   210  	// Test doesnot exist operator
   211  	t.Run("Test operator !", func(t *testing.T) {
   212  		r, err := LabelSelector([]v1alpha1.Selector{{
   213  			Key:       "key",
   214  			Operation: "!",
   215  		}})
   216  		if err != nil {
   217  			t.Fatal(err)
   218  		}
   219  		validL := &labels.Set{"notkey": "something"}
   220  		if !r.Matches(validL) {
   221  			t.Errorf("didnot match %v", validL)
   222  		}
   223  		invalidL := &labels.Set{"key": "something"}
   224  		if r.Matches(invalidL) {
   225  			t.Errorf("matched %v", invalidL)
   226  		}
   227  	})
   228  	// Test default operator
   229  	t.Run("Test default operator", func(t *testing.T) {
   230  		r, err := LabelSelector([]v1alpha1.Selector{{
   231  			Key:       "key",
   232  			Operation: "",
   233  			Value:     "something",
   234  		}})
   235  		if err != nil {
   236  			t.Fatal(err)
   237  		}
   238  		validL := &labels.Set{"key": "something"}
   239  		if !r.Matches(validL) {
   240  			t.Errorf("didnot match %v", validL)
   241  		}
   242  		invalidL := &labels.Set{"key": "not something"}
   243  		if r.Matches(invalidL) {
   244  			t.Errorf("matched %v", invalidL)
   245  		}
   246  	})
   247  	// Test invalid operators <= and >=
   248  	for _, op := range []string{"<=", ">="} {
   249  		t.Run(fmt.Sprintf("Invalid operator %v", op), func(t *testing.T) {
   250  			_, err := LabelSelector([]v1alpha1.Selector{{
   251  				Key:       "workflows.argoproj.io/phase",
   252  				Operation: op,
   253  				Value:     "1",
   254  			}})
   255  			if err == nil {
   256  				t.Errorf("Invalid operator should throw error")
   257  			}
   258  		})
   259  	}
   260  	// Test comma separated values for in
   261  	t.Run("Comma separated values", func(t *testing.T) {
   262  		r, err := LabelSelector([]v1alpha1.Selector{{
   263  			Key:       "key",
   264  			Operation: "in",
   265  			Value:     "a,b,",
   266  		}})
   267  		if err != nil {
   268  			t.Fatal("valid value threw error, value %w", err)
   269  		}
   270  		for _, validL := range []labels.Set{{"key": "a"}, {"key": "b"}, {"key": ""}} {
   271  			if !r.Matches(validL) {
   272  				t.Errorf("didnot match %v", validL)
   273  			}
   274  		}
   275  		invalidL := &labels.Set{"key": "c"}
   276  		if r.Matches(invalidL) {
   277  			t.Errorf("matched %v", invalidL)
   278  		}
   279  	})
   280  }