Merge pull request #110 from sstarcher/empty_filter
support selector that is empty
This commit is contained in:
		
						commit
						e85b87828a
					
				|  | @ -15,14 +15,16 @@ type ReleaseFilter interface { | |||
| // LabelFilter matches a release with the given positive lables. Negative labels
 | ||||
| // invert the match for cases such as tier!=backend
 | ||||
| type LabelFilter struct { | ||||
| 	positiveLabels map[string]string | ||||
| 	negativeLabels map[string]string | ||||
| 	positiveLabels [][]string | ||||
| 	negativeLabels [][]string | ||||
| } | ||||
| 
 | ||||
| // Match will match a release that has the same labels as the filter
 | ||||
| func (l LabelFilter) Match(r ReleaseSpec) bool { | ||||
| 	if len(l.positiveLabels) > 0 { | ||||
| 		for k, v := range l.positiveLabels { | ||||
| 		for _, element := range l.positiveLabels { | ||||
| 			k := element[0] | ||||
| 			v := element[1] | ||||
| 			if rVal, ok := r.Labels[k]; !ok { | ||||
| 				return false | ||||
| 			} else if rVal != v { | ||||
|  | @ -30,8 +32,11 @@ func (l LabelFilter) Match(r ReleaseSpec) bool { | |||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if len(l.negativeLabels) > 0 { | ||||
| 		for k, v := range l.negativeLabels { | ||||
| 		for _, element := range l.negativeLabels { | ||||
| 			k := element[0] | ||||
| 			v := element[1] | ||||
| 			if rVal, ok := r.Labels[k]; !ok { | ||||
| 				return true | ||||
| 			} else if rVal == v { | ||||
|  | @ -45,17 +50,17 @@ func (l LabelFilter) Match(r ReleaseSpec) bool { | |||
| // ParseLabels takes a label in the form foo=bar,baz!=bat and returns a LabelFilter that will match the labels
 | ||||
| func ParseLabels(l string) (LabelFilter, error) { | ||||
| 	lf := LabelFilter{} | ||||
| 	lf.positiveLabels = map[string]string{} | ||||
| 	lf.negativeLabels = map[string]string{} | ||||
| 	lf.positiveLabels = [][]string{} | ||||
| 	lf.negativeLabels = [][]string{} | ||||
| 	var err error | ||||
| 	labels := strings.Split(l, ",") | ||||
| 	for _, label := range labels { | ||||
| 		if match, _ := regexp.MatchString("^[a-zA-Z0-9_-]+!=[a-zA-Z0-9_-]+$", label); match == true { // k!=v case
 | ||||
| 			kv := strings.Split(label, "!=") | ||||
| 			lf.negativeLabels[kv[0]] = kv[1] | ||||
| 			lf.negativeLabels = append(lf.negativeLabels, kv) | ||||
| 		} else if match, _ := regexp.MatchString("^[a-zA-Z0-9_-]+=[a-zA-Z0-9_-]+$", label); match == true { // k=v case
 | ||||
| 			kv := strings.Split(label, "=") | ||||
| 			lf.positiveLabels[kv[0]] = kv[1] | ||||
| 			lf.positiveLabels = append(lf.positiveLabels, kv) | ||||
| 		} else { // malformed case
 | ||||
| 			err = fmt.Errorf("Malformed label: %s. Expected label in form k=v or k!=v", label) | ||||
| 		} | ||||
|  |  | |||
|  | @ -87,13 +87,13 @@ func TestReadFromYaml_FilterReleasesOnLabels(t *testing.T) { | |||
| 		filter  LabelFilter | ||||
| 		results []bool | ||||
| 	}{ | ||||
| 		{LabelFilter{positiveLabels: map[string]string{"tier": "frontend"}}, | ||||
| 		{LabelFilter{positiveLabels: [][]string{[]string{"tier", "frontend"}}}, | ||||
| 			[]bool{true, true, false}}, | ||||
| 		{LabelFilter{positiveLabels: map[string]string{"tier": "frontend", "foo": "bar"}}, | ||||
| 		{LabelFilter{positiveLabels: [][]string{[]string{"tier", "frontend"}, []string{"foo", "bar"}}}, | ||||
| 			[]bool{true, false, false}}, | ||||
| 		{LabelFilter{negativeLabels: map[string]string{"tier": "frontend"}}, | ||||
| 		{LabelFilter{negativeLabels: [][]string{[]string{"tier", "frontend"}}}, | ||||
| 			[]bool{false, false, true}}, | ||||
| 		{LabelFilter{positiveLabels: map[string]string{"tier": "frontend"}, negativeLabels: map[string]string{"foo": "bar"}}, | ||||
| 		{LabelFilter{positiveLabels: [][]string{[]string{"tier", "frontend"}}, negativeLabels: [][]string{[]string{"foo", "bar"}}}, | ||||
| 			[]bool{false, true, false}}, | ||||
| 	} | ||||
| 	state, err := readFromYaml(yamlContent, yamlFile) | ||||
|  | @ -109,18 +109,57 @@ func TestReadFromYaml_FilterReleasesOnLabels(t *testing.T) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestReadFromYaml_FilterNegatives(t *testing.T) { | ||||
| 	yamlFile := "example/path/to/yaml/file" | ||||
| 	yamlContent := []byte(`releases: | ||||
| - name: myrelease1 | ||||
|   chart: mychart1 | ||||
|   labels: | ||||
|     stage: pre | ||||
|     foo: bar | ||||
| - name: myrelease2 | ||||
|   chart: mychart2 | ||||
|   labels: | ||||
|     stage: post | ||||
| - name: myrelease3 | ||||
|   chart: mychart3 | ||||
| `) | ||||
| 	cases := []struct { | ||||
| 		filter  LabelFilter | ||||
| 		results []bool | ||||
| 	}{ | ||||
| 		{LabelFilter{positiveLabels: [][]string{[]string{"stage", "pre"}}}, | ||||
| 			[]bool{true, false, false}}, | ||||
| 		{LabelFilter{positiveLabels: [][]string{[]string{"stage", "post"}}}, | ||||
| 			[]bool{false, true, false}}, | ||||
| 		{LabelFilter{negativeLabels: [][]string{[]string{"stage", "pre"}, []string{"stage", "post"}}}, | ||||
| 			[]bool{false, false, true}}, | ||||
| 	} | ||||
| 	state, err := readFromYaml(yamlContent, yamlFile) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("unexpected error: %v", err) | ||||
| 	} | ||||
| 	for idx, c := range cases { | ||||
| 		for idx2, expected := range c.results { | ||||
| 			if f := c.filter.Match(state.Releases[idx2]); f != expected { | ||||
| 				t.Errorf("[case: %d][outcome: %d] Unexpected outcome wanted %t, got %t", idx, idx2, expected, f) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestLabelParsing(t *testing.T) { | ||||
| 	cases := []struct { | ||||
| 		labelString    string | ||||
| 		expectedFilter LabelFilter | ||||
| 		errorExected   bool | ||||
| 	}{ | ||||
| 		{"foo=bar", LabelFilter{positiveLabels: map[string]string{"foo": "bar"}, negativeLabels: map[string]string{}}, false}, | ||||
| 		{"foo!=bar", LabelFilter{positiveLabels: map[string]string{}, negativeLabels: map[string]string{"foo": "bar"}}, false}, | ||||
| 		{"foo!=bar,baz=bat", LabelFilter{positiveLabels: map[string]string{"baz": "bat"}, negativeLabels: map[string]string{"foo": "bar"}}, false}, | ||||
| 		{"foo", LabelFilter{positiveLabels: map[string]string{}, negativeLabels: map[string]string{}}, true}, | ||||
| 		{"foo!=bar=baz", LabelFilter{positiveLabels: map[string]string{}, negativeLabels: map[string]string{}}, true}, | ||||
| 		{"=bar", LabelFilter{positiveLabels: map[string]string{}, negativeLabels: map[string]string{}}, true}, | ||||
| 		{"foo=bar", LabelFilter{positiveLabels: [][]string{[]string{"foo", "bar"}}, negativeLabels: [][]string{}}, false}, | ||||
| 		{"foo!=bar", LabelFilter{positiveLabels: [][]string{}, negativeLabels: [][]string{[]string{"foo", "bar"}}}, false}, | ||||
| 		{"foo!=bar,baz=bat", LabelFilter{positiveLabels: [][]string{[]string{"baz", "bat"}}, negativeLabels: [][]string{[]string{"foo", "bar"}}}, false}, | ||||
| 		{"foo", LabelFilter{positiveLabels: [][]string{}, negativeLabels: [][]string{}}, true}, | ||||
| 		{"foo!=bar=baz", LabelFilter{positiveLabels: [][]string{}, negativeLabels: [][]string{}}, true}, | ||||
| 		{"=bar", LabelFilter{positiveLabels: [][]string{}, negativeLabels: [][]string{}}, true}, | ||||
| 	} | ||||
| 	for idx, c := range cases { | ||||
| 		filter, err := ParseLabels(c.labelString) | ||||
|  | @ -129,7 +168,7 @@ func TestLabelParsing(t *testing.T) { | |||
| 		} else if err == nil && c.errorExected { | ||||
| 			t.Errorf("[%d] Expected %s to result in an error but got none", idx, c.labelString) | ||||
| 		} else if !reflect.DeepEqual(filter, c.expectedFilter) { | ||||
| 			t.Errorf("[%d] parsed label did not result in expected filter: %v", idx, filter) | ||||
| 			t.Errorf("[%d] parsed label did not result in expected filter: %v, expected: %v", idx, filter, c.expectedFilter) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue