-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Support list expansions #2068
Conversation
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: rexagod The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
5c5949d
to
5586928
Compare
954a59a
to
0eecd57
Compare
A related #1978 Current Custom State Resource API is a little complicated. Adding more features might bring more maintaining work and make it harder to migrate into cel. I think cel can support this. |
I agree with Catherine, we shouldn't add more complexity to the existing config but rather focus on the new model. |
So, are we sunsetting the older model? |
Also, there was a thread regarding separating the CRS featureset into its own repository (the "non-turing" solution here being CEL-like languages, that do not offer an exhaustive way of defining the configuration, unlike go-based templating solutions). |
Reuse the wheel (cel, a query model) can reduce our maintaining work on how to extract fields. |
Will this mean that KSM's config capabilities will be restricted to what the underlying solution (#1978) has to offer? |
cel should be a cel is more powerful than current APIs and is capable of extracting more things. |
@dgrisonnet I'm assuming going forward with the newer model will mean we'll deprecate the older one. So, with that in mind, are PRs such as this and others like: #2067, #2052 obsolete and should be closed? |
I need to catch up on the discussions, a lot happened when I was away, but my general feeling is that we are starting to make the configuration way too complex. My fear is that this is going to become too confusing for the users and I am also worries about the current state of the parser. Without a proper lexer/parser combination this is slowly becoming unmaintainable. IMO with the state of things, we should rather focus on building new foundations for the config rather than making the existing one more complex since it will just make the migration process harder. wdyt? |
I couldn't agree more. The current CRS featureset, in addition to being complex and hardly maintainable for developers, doesn't have a clear, semantical, or easy-to-understand UX at the moment. Off the top of my mind, I can think of a few examples that go on to show a couple of such instances. I personally would not at all expect the user to be familiar with the following intricacies.
TBH only reason I raised the aforementioned PRs was because I wasn't sure about the direction in which we were going to move forward over the last month regarding this, and assumed that doing so would entail discussions spanning a good while, so things would basically be done the same way as they were till now. But, I'm enthusiastic and happy to see that there's a consensus on improving the current approach, and the discussions are yeilding actionable results. It'd be nice to see the proposed solution replacing as many configuration constructs as possible, in order to achieve a more accessible and deterministic UX for the user, thanks to @CatherineF-dev. 🎉 |
96f8b37
to
c86bc94
Compare
/hold cancel |
c86bc94
to
5159901
Compare
The Kubernetes project currently lacks enough contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle stale |
The Kubernetes project currently lacks enough active contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle rotten |
/remove-lifecycle rotten |
FYI This is up for reviews (or merging, if this looks good). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some new thoughts, I will try to have an actual look at the code later this week
We're interested in this feature and hope to see it in the next release soon! |
Allow CRS configuration to take in path values for lists, denoted by "*". This means it's possible to specify `[..., <list>, "*", foo, ...]` in the configuration to dynamically generate multiple metrics that reflect different states of `foo` in various list elements.
allow specifying dynamic valueFrom based on wildcard labelFromPaths Signed-off-by: Pranshu Srivastava <rexagod@gmail.com>
5159901
to
56b4bb7
Compare
path: mustCompilePath(t, "spec", "order", "*", "value"), | ||
want: []valuePath{ | ||
mustCompilePath(t, "spec", "order", "0", "value"), | ||
mustCompilePath(t, "spec", "order", "1", "value"), | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what would happen if value was an optional field and wasn't present in one of the order?
// search space to resolve the dynamic valueFrom from the wildcard labels | ||
dynamicValueFromScope := c.compiledCommon.labelFromPath | ||
lastUnderscoreIndex := strings.LastIndex(extractedValueFrom, "_") | ||
if lastUnderscoreIndex != -1 { | ||
// For: | ||
// labelsFromPath: | ||
// "foo_*": ["spec", "fooObj"] | ||
unresolvedKey := extractedValueFrom[:lastUnderscoreIndex] + "_*" | ||
dynamicPaths, ok := dynamicValueFromScope[unresolvedKey] | ||
if ok { | ||
var resolvedKeyArr []string | ||
for _, dynamicPath := range dynamicPaths { | ||
resolvedKeyArr = append(resolvedKeyArr, dynamicPath.part) | ||
} | ||
// resolvedKey will map to unresolved key "foo_*"'s corresponding valid path string, i.e., "spec_fooObj_*". | ||
resolvedKey := strings.Join(resolvedKeyArr, "_") | ||
extractedValueFrom = resolvedKey + extractedValueFrom[lastUnderscoreIndex:] | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we do that?
As far as I can tell this is made to propagate the wildcard to the value no? Like:
"foo_*": ["spec", "fooObj"]
yields the following path:
spec_fooObj_*
no?
handleNil := func(object interface{}, part string) interface{} { | ||
switch tobj := object.(type) { | ||
case map[string]interface{}: | ||
return tobj[part] | ||
case []interface{}: | ||
if part == "*" { | ||
return tobj | ||
} | ||
idx, err := strconv.Atoi(part) | ||
if err != nil { | ||
return nil | ||
} | ||
if idx < 0 || idx >= len(tobj) { | ||
return nil | ||
} | ||
return tobj[idx] | ||
default: | ||
return nil | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you make that its own function so that the code is easier to read?
@@ -674,14 +780,85 @@ func famGen(f compiledFamily) generator.FamilyGenerator { | |||
} | |||
} | |||
|
|||
func findWildcard(path valuePath, i *int) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not a fan of modifying the index and returning whether we find the wildcard or not. A more idiomatic approach would be similar to the search functions in the strings package where if found you return the index, otherwise -1
pathCopyStart := make(valuePath, i) | ||
copy(pathCopyStart, path[:i]) | ||
pathCopyWildcard := make(valuePath, len(path)-i-1) | ||
copy(pathCopyWildcard, path[i+1:]) | ||
for k := 0; k < l; k++ { | ||
pathCopyStart = append(pathCopyStart, pathOp{part: strconv.Itoa(k)}) | ||
pathCopyStart = append(pathCopyStart, pathCopyWildcard...) | ||
expandedPaths = append(expandedPaths, pathCopyStart) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we know the size of the path from the get go, it would be less expensive in terms of allocations to just allocate one slice and then fill it correctly
PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
The Kubernetes project currently lacks enough contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle stale |
The Kubernetes project currently lacks enough active contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle rotten |
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues and PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /close |
@k8s-triage-robot: Closed this PR. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
What this PR does / why we need it: Allow CRS configuration to take in path values for lists, denoted by "*". This means it's possible to specify
[..., <list>, "*", foo, ...]
in the configuration to dynamically generate multiple metrics that reflect different states offoo
in various list elements.How does this change affect the cardinality of KSM: No change.