-
Notifications
You must be signed in to change notification settings - Fork 1.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
Add feature flags for affinity/nodeSelector/tolerations #8645
Add feature flags for affinity/nodeSelector/tolerations #8645
Conversation
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.
@emaildanwilson: 0 warnings.
In response to this:
Fixes #1816
Proposed Changes
- Adds a flag kubernetes.podspec-affinity in config-features with a default of
disabled
- Adds a flag kubernetes.podspec-nodeselector in config-features with a default of
disabled
- Adds a flag kubernetes.podspec-tolerations in config-features with a default of
disabled
- Updates FromContextOrDefaults function to supply defaults for config-default, config-features and config-autoscaler individually when the context is missing any of those sections. A code path was discovered where features is nil.
- Adds unit tests for each feature flag, some test consolidation was done to remove some boilerplate.
Release Note
Feature flags are now available to enable affinity, nodeSelector and tolerations for Knative Services. See config-features for details.
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.
Welcome @emaildanwilson! It looks like this is your first PR to knative/serving 🎉 |
Hi @emaildanwilson. Thanks for your PR. I'm waiting for a knative member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. 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. |
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.
Produced via:
gofmt -s -w $(find -path './vendor' -prune -o -path './third_party' -prune -o -name '*.pb.go' -prune -o -type f -name '*.go' -print)
goimports -w $(find -name '*.go' | grep -v vendor | grep -v third_party | grep -v .pb.go | grep -v wire_gen.go)
1e59637
to
699476c
Compare
/assign @dprotaso |
pkg/apis/config/store.go
Outdated
if cfg := FromContext(ctx); cfg != nil { | ||
return cfg | ||
cfg := FromContext(ctx) | ||
if cfg == nil { | ||
cfg = &Config{} | ||
} | ||
defaults, _ := NewDefaultsConfigFromMap(map[string]string{}) | ||
features, _ := NewFeaturesConfigFromMap(map[string]string{}) | ||
autoscaler, _ := autoscalerconfig.NewConfigFromMap(map[string]string{}) | ||
return &Config{ | ||
Defaults: defaults, | ||
Features: features, | ||
Autoscaler: autoscaler, | ||
|
||
if cfg.Defaults == nil { | ||
defaults, _ := NewDefaultsConfigFromMap(map[string]string{}) | ||
cfg.Defaults = defaults | ||
} | ||
|
||
if cfg.Features == nil { | ||
features, _ := NewFeaturesConfigFromMap(map[string]string{}) | ||
cfg.Features = features | ||
} | ||
|
||
if cfg.Autoscaler == nil { | ||
autoscaler, _ := autoscalerconfig.NewConfigFromMap(map[string]string{}) | ||
cfg.Autoscaler = autoscaler | ||
} | ||
return cfg |
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.
This fixes a case where cfg is initialized in an autoscaler test with a context containing only autoscaling config. As a result Features is never populated and can panic when referenced. I thought it made sense to stop this from ever happening but if the preference is to add defensive code where Features is being used/or fix the autoscaler test I can make changes accordingly.
@@ -513,6 +507,138 @@ func TestPodSpecMultiContainerValidation(t *testing.T) { | |||
} | |||
} | |||
|
|||
func TestPodSpecFeatureValidation(t *testing.T) { |
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.
This iterates each podSpec feature running four tests against each feature. It makes adding new tests for new podSpec features easy and reduces the amount of duplicate test code. If this is acceptable I can move the test for FieldRef into this too. If the preference is to duplicate the code for each of these for clarity I can break them out into a test function for each one. ty.
/ok-to-test |
The following jobs failed:
Automatically retrying due to test flakiness... |
@@ -34,16 +35,9 @@ import ( | |||
|
|||
type configOption func(*config.Config) *config.Config | |||
|
|||
func withMultiContainer() configOption { | |||
func withFeature(feature string) configOption { |
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.
func withFeature(feature string) configOption { | |
func withFeature(feature string) configOption { |
Maybe withFeatureEnabled
or expand to withFeature(feature string, state Flag)
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.
+1 - I'll go with withFeatureEnabled for now since the only use case is to enable features at this point.
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.
Couple nits, but otherwise this looks like it will do the trick.
pkg/apis/config/store.go
Outdated
defaults, _ := NewDefaultsConfigFromMap(map[string]string{}) | ||
cfg.Defaults = defaults |
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.
defaults, _ := NewDefaultsConfigFromMap(map[string]string{}) | |
cfg.Defaults = defaults | |
cfg.Defaults, _ = NewDefaultsConfigFromMap(map[string]string{}) |
pkg/apis/config/store.go
Outdated
features, _ := NewFeaturesConfigFromMap(map[string]string{}) | ||
cfg.Features = features |
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.
features, _ := NewFeaturesConfigFromMap(map[string]string{}) | |
cfg.Features = features | |
cfg.Features, _ = NewFeaturesConfigFromMap(map[string]string{}) |
pkg/apis/config/store.go
Outdated
autoscaler, _ := autoscalerconfig.NewConfigFromMap(map[string]string{}) | ||
cfg.Autoscaler = autoscaler |
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.
autoscaler, _ := autoscalerconfig.NewConfigFromMap(map[string]string{}) | |
cfg.Autoscaler = autoscaler | |
cfg.Autoscaler, _ = autoscalerconfig.NewConfigFromMap(map[string]string{}) |
pkg/apis/serving/fieldmask.go
Outdated
@@ -136,7 +137,7 @@ func KeyToPathMask(in *corev1.KeyToPath) *corev1.KeyToPath { | |||
// PodSpecMask performs a _shallow_ copy of the Kubernetes PodSpec object to a new | |||
// Kubernetes PodSpec object bringing over only the fields allowed in the Knative API. This | |||
// does not validate the contents or the bounds of the provided fields. | |||
func PodSpecMask(in *corev1.PodSpec) *corev1.PodSpec { | |||
func PodSpecMask(in *corev1.PodSpec, features *config.Features) *corev1.PodSpec { |
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.
How hard would it be to plumb context into here instead?
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.
That should be easy enough. I'll give it a go.
func withFieldRef() configOption { | ||
return func(cfg *config.Config) *config.Config { | ||
cfg.Features.PodSpecFieldRef = config.Enabled | ||
reflect.Indirect(reflect.ValueOf(&cfg.Features)).Elem().FieldByName(feature).Set(reflect.ValueOf(config.Enabled)) |
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 feel like if folks hold this wrong (even a typo) they're gonna have a really bad time.
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.
Agreed but it's test code only and reduces boiler plate. If you'd still rather I spell each function out then I don't mind.
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.
let's spell it out for now.
I can imagine a simpler solution where each feature is a package constant with some helper methods to apply states on configs.
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.
ok, will do.
/assign @whaught Just to make sure that Weston's review is easily findable when he's working on his approver badge. |
pkg/apis/config/store.go
Outdated
defaults, _ := NewDefaultsConfigFromMap(map[string]string{}) | ||
cfg.Defaults = defaults |
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.
nit:
defaults, _ := NewDefaultsConfigFromMap(map[string]string{}) | |
cfg.Defaults = defaults | |
cfg.Defaults = defaultDefaultsConfig() |
pkg/apis/config/store.go
Outdated
features, _ := NewFeaturesConfigFromMap(map[string]string{}) | ||
cfg.Features = features |
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.
nit:
features, _ := NewFeaturesConfigFromMap(map[string]string{}) | |
cfg.Features = features | |
cfg.Features = defaultFeaturesConfig() |
pkg/apis/config/store.go
Outdated
} | ||
|
||
if cfg.Autoscaler == nil { | ||
autoscaler, _ := autoscalerconfig.NewConfigFromMap(map[string]string{}) |
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.
We should expose these consistently - but that's a separate issue
podSpec: corev1.PodSpec{ | ||
Containers: []corev1.Container{{ | ||
Image: "busybox", | ||
}}, | ||
}, |
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.
all the podSpecs
are the same so I wonder if we can drop as an input
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.
most likely. I was thinking there may be cases where it would be needed but clearly I didn't have one :)
pkg/apis/serving/fieldmask.go
Outdated
@@ -136,11 +139,12 @@ func KeyToPathMask(in *corev1.KeyToPath) *corev1.KeyToPath { | |||
// PodSpecMask performs a _shallow_ copy of the Kubernetes PodSpec object to a new | |||
// Kubernetes PodSpec object bringing over only the fields allowed in the Knative API. This | |||
// does not validate the contents or the bounds of the provided fields. | |||
func PodSpecMask(in *corev1.PodSpec) *corev1.PodSpec { | |||
func PodSpecMask(in *corev1.PodSpec, ctx context.Context) *corev1.PodSpec { |
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.
Can you put the context first
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.
yes, np.
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.
yes, np. done.
4c682b1
to
8c41046
Compare
update formatting improvements from review feedback spell out functions to enable features put context first
8c41046
to
c44a38a
Compare
/lgtm thanks for the PR @emaildanwilson 🎉 |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: dprotaso, emaildanwilson 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 |
The following is the coverage report on the affected files.
|
/lgtm |
Fixes #1816
Proposed Changes
disabled
disabled
disabled
Release Note