Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion config/core/configmaps/features.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ metadata:
app.kubernetes.io/version: devel
serving.knative.dev/release: devel
annotations:
knative.dev/example-checksum: "d9e300ba"
knative.dev/example-checksum: "e1c6e542"
data:
_example: |-
################################
Expand Down Expand Up @@ -53,6 +53,12 @@ data:
# See: https://knative.dev/docs/serving/feature-flags/#kubernetes-node-affinity
kubernetes.podspec-affinity: "disabled"

# Indicates whether Kubernetes topologySpreadConstraints support is enabled
#
# WARNING: Cannot safely be disabled once enabled.
# See: https://knative.dev/docs/serving/feature-flags/#kubernetes-topology-spread-constraints
kubernetes.podspec-topologyspreadconstraints: "disabled"

# Indicates whether Kubernetes hostAliases support is enabled
#
# WARNING: Cannot safely be disabled once enabled.
Expand Down
75 changes: 39 additions & 36 deletions pkg/apis/config/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,25 @@ const (

func defaultFeaturesConfig() *Features {
return &Features{
MultiContainer: Enabled,
PodSpecAffinity: Disabled,
PodSpecDryRun: Allowed,
PodSpecHostAliases: Disabled,
PodSpecFieldRef: Disabled,
PodSpecNodeSelector: Disabled,
PodSpecRuntimeClassName: Disabled,
PodSpecSecurityContext: Disabled,
PodSpecPriorityClassName: Disabled,
PodSpecSchedulerName: Disabled,
ContainerSpecAddCapabilities: Disabled,
PodSpecTolerations: Disabled,
PodSpecVolumesEmptyDir: Disabled,
PodSpecPersistentVolumeClaim: Disabled,
PodSpecPersistentVolumeWrite: Disabled,
PodSpecInitContainers: Disabled,
TagHeaderBasedRouting: Disabled,
AutoDetectHTTP2: Disabled,
MultiContainer: Enabled,
PodSpecAffinity: Disabled,
PodSpecTopologySpreadConstraints: Disabled,
PodSpecDryRun: Allowed,
PodSpecHostAliases: Disabled,
PodSpecFieldRef: Disabled,
PodSpecNodeSelector: Disabled,
PodSpecRuntimeClassName: Disabled,
PodSpecSecurityContext: Disabled,
PodSpecPriorityClassName: Disabled,
PodSpecSchedulerName: Disabled,
ContainerSpecAddCapabilities: Disabled,
PodSpecTolerations: Disabled,
PodSpecVolumesEmptyDir: Disabled,
PodSpecPersistentVolumeClaim: Disabled,
PodSpecPersistentVolumeWrite: Disabled,
PodSpecInitContainers: Disabled,
TagHeaderBasedRouting: Disabled,
AutoDetectHTTP2: Disabled,
}
}

Expand All @@ -69,6 +70,7 @@ func NewFeaturesConfigFromMap(data map[string]string) (*Features, error) {
if err := cm.Parse(data,
asFlag("multi-container", &nc.MultiContainer),
asFlag("kubernetes.podspec-affinity", &nc.PodSpecAffinity),
asFlag("kubernetes.podspec-topologyspreadconstraints", &nc.PodSpecTopologySpreadConstraints),
asFlag("kubernetes.podspec-dryrun", &nc.PodSpecDryRun),
asFlag("kubernetes.podspec-hostaliases", &nc.PodSpecHostAliases),
asFlag("kubernetes.podspec-fieldref", &nc.PodSpecFieldRef),
Expand Down Expand Up @@ -97,24 +99,25 @@ func NewFeaturesConfigFromConfigMap(config *corev1.ConfigMap) (*Features, error)

// Features specifies which features are allowed by the webhook.
type Features struct {
MultiContainer Flag
PodSpecAffinity Flag
PodSpecDryRun Flag
PodSpecFieldRef Flag
PodSpecHostAliases Flag
PodSpecNodeSelector Flag
PodSpecRuntimeClassName Flag
PodSpecSecurityContext Flag
PodSpecPriorityClassName Flag
PodSpecSchedulerName Flag
ContainerSpecAddCapabilities Flag
PodSpecTolerations Flag
PodSpecVolumesEmptyDir Flag
PodSpecInitContainers Flag
PodSpecPersistentVolumeClaim Flag
PodSpecPersistentVolumeWrite Flag
TagHeaderBasedRouting Flag
AutoDetectHTTP2 Flag
MultiContainer Flag
PodSpecAffinity Flag
PodSpecTopologySpreadConstraints Flag
PodSpecDryRun Flag
PodSpecFieldRef Flag
PodSpecHostAliases Flag
PodSpecNodeSelector Flag
PodSpecRuntimeClassName Flag
PodSpecSecurityContext Flag
PodSpecPriorityClassName Flag
PodSpecSchedulerName Flag
ContainerSpecAddCapabilities Flag
PodSpecTolerations Flag
PodSpecVolumesEmptyDir Flag
PodSpecInitContainers Flag
PodSpecPersistentVolumeClaim Flag
PodSpecPersistentVolumeWrite Flag
TagHeaderBasedRouting Flag
AutoDetectHTTP2 Flag
}

// asFlag parses the value at key as a Flag into the target, if it exists.
Expand Down
77 changes: 53 additions & 24 deletions pkg/apis/config/features_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,30 +59,32 @@ func TestFeaturesConfiguration(t *testing.T) {
name: "features Enabled",
wantErr: false,
wantFeatures: defaultWith(&Features{
MultiContainer: Enabled,
PodSpecAffinity: Enabled,
PodSpecDryRun: Enabled,
PodSpecHostAliases: Enabled,
PodSpecNodeSelector: Enabled,
PodSpecRuntimeClassName: Enabled,
PodSpecSecurityContext: Enabled,
PodSpecTolerations: Enabled,
PodSpecPriorityClassName: Enabled,
PodSpecSchedulerName: Enabled,
TagHeaderBasedRouting: Enabled,
}),
data: map[string]string{
"multi-container": "Enabled",
"kubernetes.podspec-affinity": "Enabled",
"kubernetes.podspec-dryrun": "Enabled",
"kubernetes.podspec-hostaliases": "Enabled",
"kubernetes.podspec-nodeselector": "Enabled",
"kubernetes.podspec-runtimeclassname": "Enabled",
"kubernetes.podspec-securitycontext": "Enabled",
"kubernetes.podspec-tolerations": "Enabled",
"kubernetes.podspec-priorityclassname": "Enabled",
"kubernetes.podspec-schedulername": "Enabled",
"tag-header-based-routing": "Enabled",
MultiContainer: Enabled,
PodSpecAffinity: Enabled,
PodSpecTopologySpreadConstraints: Enabled,
PodSpecDryRun: Enabled,
PodSpecHostAliases: Enabled,
PodSpecNodeSelector: Enabled,
PodSpecRuntimeClassName: Enabled,
PodSpecSecurityContext: Enabled,
PodSpecTolerations: Enabled,
PodSpecPriorityClassName: Enabled,
PodSpecSchedulerName: Enabled,
TagHeaderBasedRouting: Enabled,
}),
data: map[string]string{
"multi-container": "Enabled",
"kubernetes.podspec-affinity": "Enabled",
"kubernetes.podspec-topologyspreadconstraints": "Enabled",
"kubernetes.podspec-dryrun": "Enabled",
"kubernetes.podspec-hostaliases": "Enabled",
"kubernetes.podspec-nodeselector": "Enabled",
"kubernetes.podspec-runtimeclassname": "Enabled",
"kubernetes.podspec-securitycontext": "Enabled",
"kubernetes.podspec-tolerations": "Enabled",
"kubernetes.podspec-priorityclassname": "Enabled",
"kubernetes.podspec-schedulername": "Enabled",
"tag-header-based-routing": "Enabled",
},
}, {
name: "multi-container Allowed",
Expand Down Expand Up @@ -129,6 +131,33 @@ func TestFeaturesConfiguration(t *testing.T) {
data: map[string]string{
"kubernetes.podspec-affinity": "Disabled",
},
}, {
name: "kubernetes.podspec-topologyspreadconstraints Allowed",
wantErr: false,
wantFeatures: defaultWith(&Features{
PodSpecTopologySpreadConstraints: Allowed,
}),
data: map[string]string{
"kubernetes.podspec-topologyspreadconstraints": "Allowed",
},
}, {
name: "kubernetes.podspec-topologyspreadconstraints Enabled",
wantErr: false,
wantFeatures: defaultWith(&Features{
PodSpecTopologySpreadConstraints: Enabled,
}),
data: map[string]string{
"kubernetes.podspec-topologyspreadconstraints": "Enabled",
},
}, {
name: "kubernetes.podspec-topologyspreadconstraints Disabled",
wantErr: false,
wantFeatures: defaultWith(&Features{
PodSpecTopologySpreadConstraints: Disabled,
}),
data: map[string]string{
"kubernetes.podspec-topologyspreadconstraints": "Disabled",
},
}, {
name: "kubernetes.podspec-fieldref Allowed",
wantErr: false,
Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/serving/fieldmask.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ func PodSpecMask(ctx context.Context, in *corev1.PodSpec) *corev1.PodSpec {
if cfg.Features.PodSpecAffinity != config.Disabled {
out.Affinity = in.Affinity
}
if cfg.Features.PodSpecTopologySpreadConstraints != config.Disabled {
out.TopologySpreadConstraints = in.TopologySpreadConstraints
}
if cfg.Features.PodSpecHostAliases != config.Disabled {
out.HostAliases = in.HostAliases
}
Expand Down
29 changes: 29 additions & 0 deletions pkg/apis/serving/k8s_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

"github.com/google/go-cmp/cmp"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/validation"
Expand Down Expand Up @@ -65,6 +66,13 @@ func withPodSpecAffinityEnabled() configOption {
}
}

func withPodSpecTopologySpreadConstraintsEnabled() configOption {
return func(cfg *config.Config) *config.Config {
cfg.Features.PodSpecTopologySpreadConstraints = config.Enabled
return cfg
}
}

func withPodSpecHostAliasesEnabled() configOption {
return func(cfg *config.Config) *config.Config {
cfg.Features.PodSpecHostAliases = config.Enabled
Expand Down Expand Up @@ -1033,6 +1041,27 @@ func TestPodSpecFeatureValidation(t *testing.T) {
Paths: []string{"affinity"},
},
cfgOpts: []configOption{withPodSpecAffinityEnabled()},
}, {
name: "TopologySpreadConstraints",
featureSpec: corev1.PodSpec{
TopologySpreadConstraints: []corev1.TopologySpreadConstraint{{
MaxSkew: 1,
TopologyKey: "topology.kubernetes.io/zone",
WhenUnsatisfiable: "DoNotSchedule",
LabelSelector: &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{{
Key: "key",
Operator: "In",
Values: []string{"value"},
}},
},
}},
},
err: &apis.FieldError{
Message: "must not set the field(s)",
Paths: []string{"topologySpreadConstraints"},
},
cfgOpts: []configOption{withPodSpecTopologySpreadConstraintsEnabled()},
}, {
name: "HostAliases",
featureSpec: corev1.PodSpec{
Expand Down
29 changes: 15 additions & 14 deletions pkg/reconciler/route/resources/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,20 +421,21 @@ func testConfig() *config.Config {
TagTemplate: network.DefaultTagTemplate,
},
Features: &apiConfig.Features{
MultiContainer: apiConfig.Disabled,
PodSpecAffinity: apiConfig.Disabled,
PodSpecFieldRef: apiConfig.Disabled,
PodSpecDryRun: apiConfig.Enabled,
PodSpecHostAliases: apiConfig.Disabled,
PodSpecNodeSelector: apiConfig.Disabled,
PodSpecTolerations: apiConfig.Disabled,
PodSpecVolumesEmptyDir: apiConfig.Disabled,
PodSpecPersistentVolumeClaim: apiConfig.Disabled,
PodSpecPersistentVolumeWrite: apiConfig.Disabled,
PodSpecInitContainers: apiConfig.Disabled,
PodSpecPriorityClassName: apiConfig.Disabled,
PodSpecSchedulerName: apiConfig.Disabled,
TagHeaderBasedRouting: apiConfig.Disabled,
MultiContainer: apiConfig.Disabled,
PodSpecAffinity: apiConfig.Disabled,
PodSpecTopologySpreadConstraints: apiConfig.Disabled,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change necessary? Curious what failed when you didn't have this?

@stevenchen-db stevenchen-db Mar 14, 2022

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, I was mostly going off of this as an example PR 20be262. Is it safe to not include PodSpecTopologySpreadConstraints?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think these changes are necessary then - can you drop them

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Also deleted the line you mentioned below

PodSpecFieldRef: apiConfig.Disabled,
PodSpecDryRun: apiConfig.Enabled,
PodSpecHostAliases: apiConfig.Disabled,
PodSpecNodeSelector: apiConfig.Disabled,
PodSpecTolerations: apiConfig.Disabled,
PodSpecVolumesEmptyDir: apiConfig.Disabled,
PodSpecPersistentVolumeClaim: apiConfig.Disabled,
PodSpecPersistentVolumeWrite: apiConfig.Disabled,
PodSpecInitContainers: apiConfig.Disabled,
PodSpecPriorityClassName: apiConfig.Disabled,
PodSpecSchedulerName: apiConfig.Disabled,
TagHeaderBasedRouting: apiConfig.Disabled,
},
}
}
21 changes: 11 additions & 10 deletions pkg/reconciler/route/table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3272,16 +3272,17 @@ func reconcilerTestConfig() *config.Config {
DefaultExternalScheme: "http",
},
Features: &cfgmap.Features{
MultiContainer: cfgmap.Disabled,
PodSpecAffinity: cfgmap.Disabled,
PodSpecFieldRef: cfgmap.Disabled,
PodSpecDryRun: cfgmap.Enabled,
PodSpecHostAliases: cfgmap.Disabled,
PodSpecNodeSelector: cfgmap.Disabled,
PodSpecTolerations: cfgmap.Disabled,
PodSpecPriorityClassName: cfgmap.Disabled,
PodSpecSchedulerName: cfgmap.Disabled,
TagHeaderBasedRouting: cfgmap.Disabled,
MultiContainer: cfgmap.Disabled,
PodSpecAffinity: cfgmap.Disabled,
PodSpecTopologySpreadConstraints: cfgmap.Disabled,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same question as above

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same answer as above

PodSpecFieldRef: cfgmap.Disabled,
PodSpecDryRun: cfgmap.Enabled,
PodSpecHostAliases: cfgmap.Disabled,
PodSpecNodeSelector: cfgmap.Disabled,
PodSpecTolerations: cfgmap.Disabled,
PodSpecPriorityClassName: cfgmap.Disabled,
PodSpecSchedulerName: cfgmap.Disabled,
TagHeaderBasedRouting: cfgmap.Disabled,
},
}
}
Expand Down