fix(deps): update module github.com/onsi/ginkgo/v2 to v2.19.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									c24e0cbfe7
								
							
						
					
					
						commit
						c5597cb12c
					
				
							
								
								
									
										2
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										2
									
								
								go.mod
								
								
								
								
							|  | @ -52,7 +52,7 @@ require ( | |||
| 	github.com/moby/sys/user v0.1.0 | ||||
| 	github.com/moby/term v0.5.0 | ||||
| 	github.com/nxadm/tail v1.4.11 | ||||
| 	github.com/onsi/ginkgo/v2 v2.18.0 | ||||
| 	github.com/onsi/ginkgo/v2 v2.19.0 | ||||
| 	github.com/onsi/gomega v1.33.1 | ||||
| 	github.com/opencontainers/go-digest v1.0.0 | ||||
| 	github.com/opencontainers/image-spec v1.1.0 | ||||
|  |  | |||
							
								
								
									
										4
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										4
									
								
								go.sum
								
								
								
								
							|  | @ -397,8 +397,8 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W | |||
| github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | ||||
| github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= | ||||
| github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= | ||||
| github.com/onsi/ginkgo/v2 v2.18.0 h1:W9Y7IWXxPUpAit9ieMOLI7PJZGaW22DTKgiVAuhDTLc= | ||||
| github.com/onsi/ginkgo/v2 v2.18.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= | ||||
| github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= | ||||
| github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= | ||||
| github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= | ||||
| github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= | ||||
| github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ go 1.20 | |||
| require ( | ||||
| 	github.com/cpuguy83/go-md2man/v2 v2.0.4 | ||||
| 	github.com/go-swagger/go-swagger v0.30.5 | ||||
| 	github.com/onsi/ginkgo/v2 v2.18.0 | ||||
| 	github.com/onsi/ginkgo/v2 v2.19.0 | ||||
| 	github.com/vbatts/git-validation v1.2.1 | ||||
| 	golang.org/x/tools v0.21.0 | ||||
| ) | ||||
|  |  | |||
|  | @ -280,8 +280,8 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJ | |||
| github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= | ||||
| github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= | ||||
| github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= | ||||
| github.com/onsi/ginkgo/v2 v2.18.0 h1:W9Y7IWXxPUpAit9ieMOLI7PJZGaW22DTKgiVAuhDTLc= | ||||
| github.com/onsi/ginkgo/v2 v2.18.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= | ||||
| github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= | ||||
| github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= | ||||
| github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= | ||||
| github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= | ||||
| github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= | ||||
|  |  | |||
|  | @ -45,6 +45,83 @@ func orAction(a, b LabelFilter) LabelFilter { | |||
| 	return func(labels []string) bool { return a(labels) || b(labels) } | ||||
| } | ||||
| 
 | ||||
| func labelSetFor(key string, labels []string) map[string]bool { | ||||
| 	key = strings.ToLower(strings.TrimSpace(key)) | ||||
| 	out := map[string]bool{} | ||||
| 	for _, label := range labels { | ||||
| 		components := strings.SplitN(label, ":", 2) | ||||
| 		if len(components) < 2 { | ||||
| 			continue | ||||
| 		} | ||||
| 		if key == strings.ToLower(strings.TrimSpace(components[0])) { | ||||
| 			out[strings.ToLower(strings.TrimSpace(components[1]))] = true | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return out | ||||
| } | ||||
| 
 | ||||
| func isEmptyLabelSetAction(key string) LabelFilter { | ||||
| 	return func(labels []string) bool { | ||||
| 		return len(labelSetFor(key, labels)) == 0 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func containsAnyLabelSetAction(key string, expectedValues []string) LabelFilter { | ||||
| 	return func(labels []string) bool { | ||||
| 		set := labelSetFor(key, labels) | ||||
| 		for _, value := range expectedValues { | ||||
| 			if set[value] { | ||||
| 				return true | ||||
| 			} | ||||
| 		} | ||||
| 		return false | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func containsAllLabelSetAction(key string, expectedValues []string) LabelFilter { | ||||
| 	return func(labels []string) bool { | ||||
| 		set := labelSetFor(key, labels) | ||||
| 		for _, value := range expectedValues { | ||||
| 			if !set[value] { | ||||
| 				return false | ||||
| 			} | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func consistsOfLabelSetAction(key string, expectedValues []string) LabelFilter { | ||||
| 	return func(labels []string) bool { | ||||
| 		set := labelSetFor(key, labels) | ||||
| 		if len(set) != len(expectedValues) { | ||||
| 			return false | ||||
| 		} | ||||
| 		for _, value := range expectedValues { | ||||
| 			if !set[value] { | ||||
| 				return false | ||||
| 			} | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func isSubsetOfLabelSetAction(key string, expectedValues []string) LabelFilter { | ||||
| 	expectedSet := map[string]bool{} | ||||
| 	for _, value := range expectedValues { | ||||
| 		expectedSet[value] = true | ||||
| 	} | ||||
| 	return func(labels []string) bool { | ||||
| 		set := labelSetFor(key, labels) | ||||
| 		for value := range set { | ||||
| 			if !expectedSet[value] { | ||||
| 				return false | ||||
| 			} | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type lfToken uint | ||||
| 
 | ||||
| const ( | ||||
|  | @ -58,6 +135,9 @@ const ( | |||
| 	lfTokenOr | ||||
| 	lfTokenRegexp | ||||
| 	lfTokenLabel | ||||
| 	lfTokenSetKey | ||||
| 	lfTokenSetOperation | ||||
| 	lfTokenSetArgument | ||||
| 	lfTokenEOF | ||||
| ) | ||||
| 
 | ||||
|  | @ -71,6 +151,8 @@ func (l lfToken) Precedence() int { | |||
| 		return 2 | ||||
| 	case lfTokenNot: | ||||
| 		return 3 | ||||
| 	case lfTokenSetOperation: | ||||
| 		return 4 | ||||
| 	} | ||||
| 	return -1 | ||||
| } | ||||
|  | @ -93,6 +175,12 @@ func (l lfToken) String() string { | |||
| 		return "/regexp/" | ||||
| 	case lfTokenLabel: | ||||
| 		return "label" | ||||
| 	case lfTokenSetKey: | ||||
| 		return "set_key" | ||||
| 	case lfTokenSetOperation: | ||||
| 		return "set_operation" | ||||
| 	case lfTokenSetArgument: | ||||
| 		return "set_argument" | ||||
| 	case lfTokenEOF: | ||||
| 		return "EOF" | ||||
| 	} | ||||
|  | @ -148,6 +236,35 @@ func (tn *treeNode) constructLabelFilter(input string) (LabelFilter, error) { | |||
| 			return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.location, fmt.Sprintf("RegExp compilation error: %s", err)) | ||||
| 		} | ||||
| 		return matchLabelRegexAction(re), nil | ||||
| 	case lfTokenSetOperation: | ||||
| 		tokenSetOperation := strings.ToLower(tn.value) | ||||
| 		if tokenSetOperation == "isempty" { | ||||
| 			return isEmptyLabelSetAction(tn.leftNode.value), nil | ||||
| 		} | ||||
| 		if tn.rightNode == nil { | ||||
| 			return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.location, fmt.Sprintf("Set operation '%s' is missing an argument.", tn.value)) | ||||
| 		} | ||||
| 
 | ||||
| 		rawValues := strings.Split(tn.rightNode.value, ",") | ||||
| 		values := make([]string, len(rawValues)) | ||||
| 		for i := range rawValues { | ||||
| 			values[i] = strings.ToLower(strings.TrimSpace(rawValues[i])) | ||||
| 			if strings.ContainsAny(values[i], "&|!,()/") { | ||||
| 				return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.rightNode.location, fmt.Sprintf("Invalid label value '%s' in set operation argument.", values[i])) | ||||
| 			} else if values[i] == "" { | ||||
| 				return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.rightNode.location, "Empty label value in set operation argument.") | ||||
| 			} | ||||
| 		} | ||||
| 		switch tokenSetOperation { | ||||
| 		case "containsany": | ||||
| 			return containsAnyLabelSetAction(tn.leftNode.value, values), nil | ||||
| 		case "containsall": | ||||
| 			return containsAllLabelSetAction(tn.leftNode.value, values), nil | ||||
| 		case "consistsof": | ||||
| 			return consistsOfLabelSetAction(tn.leftNode.value, values), nil | ||||
| 		case "issubsetof": | ||||
| 			return isSubsetOfLabelSetAction(tn.leftNode.value, values), nil | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if tn.rightNode == nil { | ||||
|  | @ -203,7 +320,17 @@ func (tn *treeNode) toString(indent int) string { | |||
| 	return out | ||||
| } | ||||
| 
 | ||||
| var validSetOperations = map[string]string{ | ||||
| 	"containsany": "containsAny", | ||||
| 	"containsall": "containsAll", | ||||
| 	"consistsof":  "consistsOf", | ||||
| 	"issubsetof":  "isSubsetOf", | ||||
| 	"isempty":     "isEmpty", | ||||
| } | ||||
| 
 | ||||
| func tokenize(input string) func() (*treeNode, error) { | ||||
| 	lastToken := lfTokenInvalid | ||||
| 	lastValue := "" | ||||
| 	runes, i := []rune(input), 0 | ||||
| 
 | ||||
| 	peekIs := func(r rune) bool { | ||||
|  | @ -233,6 +360,53 @@ func tokenize(input string) func() (*treeNode, error) { | |||
| 		} | ||||
| 
 | ||||
| 		node := &treeNode{location: i} | ||||
| 		defer func() { | ||||
| 			lastToken = node.token | ||||
| 			lastValue = node.value | ||||
| 		}() | ||||
| 
 | ||||
| 		if lastToken == lfTokenSetKey { | ||||
| 			//we should get a valid set operation next
 | ||||
| 			value, n := consumeUntil(" )") | ||||
| 			if validSetOperations[strings.ToLower(value)] == "" { | ||||
| 				return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i, fmt.Sprintf("Invalid set operation '%s'.", value)) | ||||
| 			} | ||||
| 			i += n | ||||
| 			node.token, node.value = lfTokenSetOperation, value | ||||
| 			return node, nil | ||||
| 		} | ||||
| 		if lastToken == lfTokenSetOperation { | ||||
| 			//we should get an argument next, if we aren't isempty
 | ||||
| 			var arg = "" | ||||
| 			origI := i | ||||
| 			if runes[i] == '{' { | ||||
| 				i += 1 | ||||
| 				value, n := consumeUntil("}") | ||||
| 				if i+n >= len(runes) { | ||||
| 					return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i-1, "Missing closing '}' in set operation argument?") | ||||
| 				} | ||||
| 				i += n + 1 | ||||
| 				arg = value | ||||
| 			} else { | ||||
| 				value, n := consumeUntil("&|!,()/") | ||||
| 				i += n | ||||
| 				arg = strings.TrimSpace(value) | ||||
| 			} | ||||
| 			if strings.ToLower(lastValue) == "isempty" && arg != "" { | ||||
| 				return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, origI, fmt.Sprintf("isEmpty does not take arguments, was passed '%s'.", arg)) | ||||
| 			} | ||||
| 			if arg == "" && strings.ToLower(lastValue) != "isempty" { | ||||
| 				if i < len(runes) && runes[i] == '/' { | ||||
| 					return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, origI, "Set operations do not support regular expressions.") | ||||
| 				} else { | ||||
| 					return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, origI, fmt.Sprintf("Set operation '%s' requires an argument.", lastValue)) | ||||
| 				} | ||||
| 			} | ||||
| 			// note that we sent an empty SetArgument token if we are isempty
 | ||||
| 			node.token, node.value = lfTokenSetArgument, arg | ||||
| 			return node, nil | ||||
| 		} | ||||
| 
 | ||||
| 		switch runes[i] { | ||||
| 		case '&': | ||||
| 			if !peekIs('&') { | ||||
|  | @ -264,8 +438,38 @@ func tokenize(input string) func() (*treeNode, error) { | |||
| 			i += n + 1 | ||||
| 			node.token, node.value = lfTokenRegexp, value | ||||
| 		default: | ||||
| 			value, n := consumeUntil("&|!,()/") | ||||
| 			value, n := consumeUntil("&|!,()/:") | ||||
| 			i += n | ||||
| 			value = strings.TrimSpace(value) | ||||
| 
 | ||||
| 			//are we the beginning of a set operation?
 | ||||
| 			if i < len(runes) && runes[i] == ':' { | ||||
| 				if peekIs(' ') { | ||||
| 					if value == "" { | ||||
| 						return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i, "Missing set key.") | ||||
| 					} | ||||
| 					i += 1 | ||||
| 					//we are the beginning of a set operation
 | ||||
| 					node.token, node.value = lfTokenSetKey, value | ||||
| 					return node, nil | ||||
| 				} | ||||
| 				additionalValue, n := consumeUntil("&|!,()/") | ||||
| 				additionalValue = strings.TrimSpace(additionalValue) | ||||
| 				if additionalValue == ":" { | ||||
| 					return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i, "Missing set operation.") | ||||
| 				} | ||||
| 				i += n | ||||
| 				value += additionalValue | ||||
| 			} | ||||
| 
 | ||||
| 			valueToCheckForSetOperation := strings.ToLower(value) | ||||
| 			for setOperation := range validSetOperations { | ||||
| 				idx := strings.Index(valueToCheckForSetOperation, " "+setOperation) | ||||
| 				if idx > 0 { | ||||
| 					return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i-n+idx+1, fmt.Sprintf("Looks like you are using the set operator '%s' but did not provide a set key.  Did you forget the ':'?", validSetOperations[setOperation])) | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			node.token, node.value = lfTokenLabel, strings.TrimSpace(value) | ||||
| 		} | ||||
| 		return node, nil | ||||
|  | @ -307,7 +511,7 @@ LOOP: | |||
| 		switch node.token { | ||||
| 		case lfTokenEOF: | ||||
| 			break LOOP | ||||
| 		case lfTokenLabel, lfTokenRegexp: | ||||
| 		case lfTokenLabel, lfTokenRegexp, lfTokenSetKey: | ||||
| 			if current.rightNode != nil { | ||||
| 				return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, node.location, "Found two adjacent labels.  You need an operator between them.") | ||||
| 			} | ||||
|  | @ -326,6 +530,18 @@ LOOP: | |||
| 			node.setLeftNode(nodeToStealFrom.rightNode) | ||||
| 			nodeToStealFrom.setRightNode(node) | ||||
| 			current = node | ||||
| 		case lfTokenSetOperation: | ||||
| 			if current.rightNode == nil { | ||||
| 				return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, node.location, fmt.Sprintf("Set operation '%s' missing left hand operand.", node.value)) | ||||
| 			} | ||||
| 			node.setLeftNode(current.rightNode) | ||||
| 			current.setRightNode(node) | ||||
| 			current = node | ||||
| 		case lfTokenSetArgument: | ||||
| 			if current.rightNode != nil { | ||||
| 				return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, node.location, fmt.Sprintf("Unexpected set argument '%s'.", node.token)) | ||||
| 			} | ||||
| 			current.setRightNode(node) | ||||
| 		case lfTokenCloseGroup: | ||||
| 			firstUnmatchedOpenNode := current.firstUnmatchedOpenNode() | ||||
| 			if firstUnmatchedOpenNode == nil { | ||||
|  | @ -354,5 +570,14 @@ func ValidateAndCleanupLabel(label string, cl CodeLocation) (string, error) { | |||
| 	if strings.ContainsAny(out, "&|!,()/") { | ||||
| 		return "", GinkgoErrors.InvalidLabel(label, cl) | ||||
| 	} | ||||
| 	if out[0] == ':' { | ||||
| 		return "", GinkgoErrors.InvalidLabel(label, cl) | ||||
| 	} | ||||
| 	if strings.Contains(out, ":") { | ||||
| 		components := strings.SplitN(out, ":", 2) | ||||
| 		if len(components) < 2 || components[1] == "" { | ||||
| 			return "", GinkgoErrors.InvalidLabel(label, cl) | ||||
| 		} | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  |  | |||
|  | @ -1,3 +1,3 @@ | |||
| package types | ||||
| 
 | ||||
| const VERSION = "2.18.0" | ||||
| const VERSION = "2.19.0" | ||||
|  |  | |||
|  | @ -154,7 +154,7 @@ github.com/mitchellh/reflectwalk | |||
| # github.com/oklog/ulid v1.3.1 | ||||
| ## explicit | ||||
| github.com/oklog/ulid | ||||
| # github.com/onsi/ginkgo/v2 v2.18.0 | ||||
| # github.com/onsi/ginkgo/v2 v2.19.0 | ||||
| ## explicit; go 1.20 | ||||
| github.com/onsi/ginkgo/v2/config | ||||
| github.com/onsi/ginkgo/v2/formatter | ||||
|  |  | |||
|  | @ -1,3 +1,9 @@ | |||
| ## 2.19.0 | ||||
| 
 | ||||
| ### Features | ||||
| 
 | ||||
| [Label Sets](https://onsi.github.io/ginkgo/#label-sets) allow for more expressive and flexible label filtering. | ||||
| 
 | ||||
| ## 2.18.0 | ||||
| 
 | ||||
| ### Features | ||||
|  |  | |||
|  | @ -45,6 +45,83 @@ func orAction(a, b LabelFilter) LabelFilter { | |||
| 	return func(labels []string) bool { return a(labels) || b(labels) } | ||||
| } | ||||
| 
 | ||||
| func labelSetFor(key string, labels []string) map[string]bool { | ||||
| 	key = strings.ToLower(strings.TrimSpace(key)) | ||||
| 	out := map[string]bool{} | ||||
| 	for _, label := range labels { | ||||
| 		components := strings.SplitN(label, ":", 2) | ||||
| 		if len(components) < 2 { | ||||
| 			continue | ||||
| 		} | ||||
| 		if key == strings.ToLower(strings.TrimSpace(components[0])) { | ||||
| 			out[strings.ToLower(strings.TrimSpace(components[1]))] = true | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return out | ||||
| } | ||||
| 
 | ||||
| func isEmptyLabelSetAction(key string) LabelFilter { | ||||
| 	return func(labels []string) bool { | ||||
| 		return len(labelSetFor(key, labels)) == 0 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func containsAnyLabelSetAction(key string, expectedValues []string) LabelFilter { | ||||
| 	return func(labels []string) bool { | ||||
| 		set := labelSetFor(key, labels) | ||||
| 		for _, value := range expectedValues { | ||||
| 			if set[value] { | ||||
| 				return true | ||||
| 			} | ||||
| 		} | ||||
| 		return false | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func containsAllLabelSetAction(key string, expectedValues []string) LabelFilter { | ||||
| 	return func(labels []string) bool { | ||||
| 		set := labelSetFor(key, labels) | ||||
| 		for _, value := range expectedValues { | ||||
| 			if !set[value] { | ||||
| 				return false | ||||
| 			} | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func consistsOfLabelSetAction(key string, expectedValues []string) LabelFilter { | ||||
| 	return func(labels []string) bool { | ||||
| 		set := labelSetFor(key, labels) | ||||
| 		if len(set) != len(expectedValues) { | ||||
| 			return false | ||||
| 		} | ||||
| 		for _, value := range expectedValues { | ||||
| 			if !set[value] { | ||||
| 				return false | ||||
| 			} | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func isSubsetOfLabelSetAction(key string, expectedValues []string) LabelFilter { | ||||
| 	expectedSet := map[string]bool{} | ||||
| 	for _, value := range expectedValues { | ||||
| 		expectedSet[value] = true | ||||
| 	} | ||||
| 	return func(labels []string) bool { | ||||
| 		set := labelSetFor(key, labels) | ||||
| 		for value := range set { | ||||
| 			if !expectedSet[value] { | ||||
| 				return false | ||||
| 			} | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type lfToken uint | ||||
| 
 | ||||
| const ( | ||||
|  | @ -58,6 +135,9 @@ const ( | |||
| 	lfTokenOr | ||||
| 	lfTokenRegexp | ||||
| 	lfTokenLabel | ||||
| 	lfTokenSetKey | ||||
| 	lfTokenSetOperation | ||||
| 	lfTokenSetArgument | ||||
| 	lfTokenEOF | ||||
| ) | ||||
| 
 | ||||
|  | @ -71,6 +151,8 @@ func (l lfToken) Precedence() int { | |||
| 		return 2 | ||||
| 	case lfTokenNot: | ||||
| 		return 3 | ||||
| 	case lfTokenSetOperation: | ||||
| 		return 4 | ||||
| 	} | ||||
| 	return -1 | ||||
| } | ||||
|  | @ -93,6 +175,12 @@ func (l lfToken) String() string { | |||
| 		return "/regexp/" | ||||
| 	case lfTokenLabel: | ||||
| 		return "label" | ||||
| 	case lfTokenSetKey: | ||||
| 		return "set_key" | ||||
| 	case lfTokenSetOperation: | ||||
| 		return "set_operation" | ||||
| 	case lfTokenSetArgument: | ||||
| 		return "set_argument" | ||||
| 	case lfTokenEOF: | ||||
| 		return "EOF" | ||||
| 	} | ||||
|  | @ -148,6 +236,35 @@ func (tn *treeNode) constructLabelFilter(input string) (LabelFilter, error) { | |||
| 			return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.location, fmt.Sprintf("RegExp compilation error: %s", err)) | ||||
| 		} | ||||
| 		return matchLabelRegexAction(re), nil | ||||
| 	case lfTokenSetOperation: | ||||
| 		tokenSetOperation := strings.ToLower(tn.value) | ||||
| 		if tokenSetOperation == "isempty" { | ||||
| 			return isEmptyLabelSetAction(tn.leftNode.value), nil | ||||
| 		} | ||||
| 		if tn.rightNode == nil { | ||||
| 			return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.location, fmt.Sprintf("Set operation '%s' is missing an argument.", tn.value)) | ||||
| 		} | ||||
| 
 | ||||
| 		rawValues := strings.Split(tn.rightNode.value, ",") | ||||
| 		values := make([]string, len(rawValues)) | ||||
| 		for i := range rawValues { | ||||
| 			values[i] = strings.ToLower(strings.TrimSpace(rawValues[i])) | ||||
| 			if strings.ContainsAny(values[i], "&|!,()/") { | ||||
| 				return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.rightNode.location, fmt.Sprintf("Invalid label value '%s' in set operation argument.", values[i])) | ||||
| 			} else if values[i] == "" { | ||||
| 				return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.rightNode.location, "Empty label value in set operation argument.") | ||||
| 			} | ||||
| 		} | ||||
| 		switch tokenSetOperation { | ||||
| 		case "containsany": | ||||
| 			return containsAnyLabelSetAction(tn.leftNode.value, values), nil | ||||
| 		case "containsall": | ||||
| 			return containsAllLabelSetAction(tn.leftNode.value, values), nil | ||||
| 		case "consistsof": | ||||
| 			return consistsOfLabelSetAction(tn.leftNode.value, values), nil | ||||
| 		case "issubsetof": | ||||
| 			return isSubsetOfLabelSetAction(tn.leftNode.value, values), nil | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if tn.rightNode == nil { | ||||
|  | @ -203,7 +320,17 @@ func (tn *treeNode) toString(indent int) string { | |||
| 	return out | ||||
| } | ||||
| 
 | ||||
| var validSetOperations = map[string]string{ | ||||
| 	"containsany": "containsAny", | ||||
| 	"containsall": "containsAll", | ||||
| 	"consistsof":  "consistsOf", | ||||
| 	"issubsetof":  "isSubsetOf", | ||||
| 	"isempty":     "isEmpty", | ||||
| } | ||||
| 
 | ||||
| func tokenize(input string) func() (*treeNode, error) { | ||||
| 	lastToken := lfTokenInvalid | ||||
| 	lastValue := "" | ||||
| 	runes, i := []rune(input), 0 | ||||
| 
 | ||||
| 	peekIs := func(r rune) bool { | ||||
|  | @ -233,6 +360,53 @@ func tokenize(input string) func() (*treeNode, error) { | |||
| 		} | ||||
| 
 | ||||
| 		node := &treeNode{location: i} | ||||
| 		defer func() { | ||||
| 			lastToken = node.token | ||||
| 			lastValue = node.value | ||||
| 		}() | ||||
| 
 | ||||
| 		if lastToken == lfTokenSetKey { | ||||
| 			//we should get a valid set operation next
 | ||||
| 			value, n := consumeUntil(" )") | ||||
| 			if validSetOperations[strings.ToLower(value)] == "" { | ||||
| 				return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i, fmt.Sprintf("Invalid set operation '%s'.", value)) | ||||
| 			} | ||||
| 			i += n | ||||
| 			node.token, node.value = lfTokenSetOperation, value | ||||
| 			return node, nil | ||||
| 		} | ||||
| 		if lastToken == lfTokenSetOperation { | ||||
| 			//we should get an argument next, if we aren't isempty
 | ||||
| 			var arg = "" | ||||
| 			origI := i | ||||
| 			if runes[i] == '{' { | ||||
| 				i += 1 | ||||
| 				value, n := consumeUntil("}") | ||||
| 				if i+n >= len(runes) { | ||||
| 					return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i-1, "Missing closing '}' in set operation argument?") | ||||
| 				} | ||||
| 				i += n + 1 | ||||
| 				arg = value | ||||
| 			} else { | ||||
| 				value, n := consumeUntil("&|!,()/") | ||||
| 				i += n | ||||
| 				arg = strings.TrimSpace(value) | ||||
| 			} | ||||
| 			if strings.ToLower(lastValue) == "isempty" && arg != "" { | ||||
| 				return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, origI, fmt.Sprintf("isEmpty does not take arguments, was passed '%s'.", arg)) | ||||
| 			} | ||||
| 			if arg == "" && strings.ToLower(lastValue) != "isempty" { | ||||
| 				if i < len(runes) && runes[i] == '/' { | ||||
| 					return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, origI, "Set operations do not support regular expressions.") | ||||
| 				} else { | ||||
| 					return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, origI, fmt.Sprintf("Set operation '%s' requires an argument.", lastValue)) | ||||
| 				} | ||||
| 			} | ||||
| 			// note that we sent an empty SetArgument token if we are isempty
 | ||||
| 			node.token, node.value = lfTokenSetArgument, arg | ||||
| 			return node, nil | ||||
| 		} | ||||
| 
 | ||||
| 		switch runes[i] { | ||||
| 		case '&': | ||||
| 			if !peekIs('&') { | ||||
|  | @ -264,8 +438,38 @@ func tokenize(input string) func() (*treeNode, error) { | |||
| 			i += n + 1 | ||||
| 			node.token, node.value = lfTokenRegexp, value | ||||
| 		default: | ||||
| 			value, n := consumeUntil("&|!,()/") | ||||
| 			value, n := consumeUntil("&|!,()/:") | ||||
| 			i += n | ||||
| 			value = strings.TrimSpace(value) | ||||
| 
 | ||||
| 			//are we the beginning of a set operation?
 | ||||
| 			if i < len(runes) && runes[i] == ':' { | ||||
| 				if peekIs(' ') { | ||||
| 					if value == "" { | ||||
| 						return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i, "Missing set key.") | ||||
| 					} | ||||
| 					i += 1 | ||||
| 					//we are the beginning of a set operation
 | ||||
| 					node.token, node.value = lfTokenSetKey, value | ||||
| 					return node, nil | ||||
| 				} | ||||
| 				additionalValue, n := consumeUntil("&|!,()/") | ||||
| 				additionalValue = strings.TrimSpace(additionalValue) | ||||
| 				if additionalValue == ":" { | ||||
| 					return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i, "Missing set operation.") | ||||
| 				} | ||||
| 				i += n | ||||
| 				value += additionalValue | ||||
| 			} | ||||
| 
 | ||||
| 			valueToCheckForSetOperation := strings.ToLower(value) | ||||
| 			for setOperation := range validSetOperations { | ||||
| 				idx := strings.Index(valueToCheckForSetOperation, " "+setOperation) | ||||
| 				if idx > 0 { | ||||
| 					return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i-n+idx+1, fmt.Sprintf("Looks like you are using the set operator '%s' but did not provide a set key.  Did you forget the ':'?", validSetOperations[setOperation])) | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			node.token, node.value = lfTokenLabel, strings.TrimSpace(value) | ||||
| 		} | ||||
| 		return node, nil | ||||
|  | @ -307,7 +511,7 @@ LOOP: | |||
| 		switch node.token { | ||||
| 		case lfTokenEOF: | ||||
| 			break LOOP | ||||
| 		case lfTokenLabel, lfTokenRegexp: | ||||
| 		case lfTokenLabel, lfTokenRegexp, lfTokenSetKey: | ||||
| 			if current.rightNode != nil { | ||||
| 				return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, node.location, "Found two adjacent labels.  You need an operator between them.") | ||||
| 			} | ||||
|  | @ -326,6 +530,18 @@ LOOP: | |||
| 			node.setLeftNode(nodeToStealFrom.rightNode) | ||||
| 			nodeToStealFrom.setRightNode(node) | ||||
| 			current = node | ||||
| 		case lfTokenSetOperation: | ||||
| 			if current.rightNode == nil { | ||||
| 				return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, node.location, fmt.Sprintf("Set operation '%s' missing left hand operand.", node.value)) | ||||
| 			} | ||||
| 			node.setLeftNode(current.rightNode) | ||||
| 			current.setRightNode(node) | ||||
| 			current = node | ||||
| 		case lfTokenSetArgument: | ||||
| 			if current.rightNode != nil { | ||||
| 				return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, node.location, fmt.Sprintf("Unexpected set argument '%s'.", node.token)) | ||||
| 			} | ||||
| 			current.setRightNode(node) | ||||
| 		case lfTokenCloseGroup: | ||||
| 			firstUnmatchedOpenNode := current.firstUnmatchedOpenNode() | ||||
| 			if firstUnmatchedOpenNode == nil { | ||||
|  | @ -354,5 +570,14 @@ func ValidateAndCleanupLabel(label string, cl CodeLocation) (string, error) { | |||
| 	if strings.ContainsAny(out, "&|!,()/") { | ||||
| 		return "", GinkgoErrors.InvalidLabel(label, cl) | ||||
| 	} | ||||
| 	if out[0] == ':' { | ||||
| 		return "", GinkgoErrors.InvalidLabel(label, cl) | ||||
| 	} | ||||
| 	if strings.Contains(out, ":") { | ||||
| 		components := strings.SplitN(out, ":", 2) | ||||
| 		if len(components) < 2 || components[1] == "" { | ||||
| 			return "", GinkgoErrors.InvalidLabel(label, cl) | ||||
| 		} | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  |  | |||
|  | @ -1,3 +1,3 @@ | |||
| package types | ||||
| 
 | ||||
| const VERSION = "2.18.0" | ||||
| const VERSION = "2.19.0" | ||||
|  |  | |||
|  | @ -840,7 +840,7 @@ github.com/nxadm/tail/winfile | |||
| # github.com/oklog/ulid v1.3.1 | ||||
| ## explicit | ||||
| github.com/oklog/ulid | ||||
| # github.com/onsi/ginkgo/v2 v2.18.0 | ||||
| # github.com/onsi/ginkgo/v2 v2.19.0 | ||||
| ## explicit; go 1.20 | ||||
| github.com/onsi/ginkgo/v2 | ||||
| github.com/onsi/ginkgo/v2/config | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue