mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-14 21:53:52 +00:00
Identify cluster scope by a boolean field rather than a special namespace
This commit is contained in:
@@ -29,7 +29,6 @@ const (
|
|||||||
NameAll = "*"
|
NameAll = "*"
|
||||||
|
|
||||||
NamespaceEvery = "*" // matches every particular namespace
|
NamespaceEvery = "*" // matches every particular namespace
|
||||||
NamespaceClusterScope = "Cluster Scope" // matches absence of namespace
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// System preset priority level names
|
// System preset priority level names
|
||||||
@@ -240,29 +239,23 @@ type ResourcePolicyRule struct {
|
|||||||
// +listType=set
|
// +listType=set
|
||||||
Resources []string
|
Resources []string
|
||||||
|
|
||||||
|
// `clusterScope` indicates whether to match requests that do not
|
||||||
|
// specify a namespace (which happens either because the resource
|
||||||
|
// is not namespaced or the request targets all namespaces).
|
||||||
|
// If this field is omitted or false then the `namespaces` field
|
||||||
|
// must contain a non-empty list.
|
||||||
|
// +optional
|
||||||
|
ClusterScope bool
|
||||||
|
|
||||||
// `namespaces` is a list of target namespaces that restricts
|
// `namespaces` is a list of target namespaces that restricts
|
||||||
// matches. A request that does not specify a target namespace
|
// matches. A request that specifies a target namespace matches
|
||||||
// (which happens both when the resource is not namespaced and
|
// only if either (a) this list contains that target namespace or
|
||||||
// when the resource is namespaced and the request is for all
|
// (b) this list contains "*". Note that "*" matches any
|
||||||
// namespaces) matches only if this list includes "Cluster Scope"
|
// specified namespace but does not match a request that _does
|
||||||
// (this string is not a valid namespace and thus can not be
|
// not specify_ a namespace (see the `clusterScope` field for
|
||||||
// confused with an actual namespace). A request that specifies a
|
// that).
|
||||||
// target namespace matches only if either (a) this list contains
|
// This list may be empty, but only if `clusterScope` is true.
|
||||||
// that target namespace or (b) this list contains "*".
|
// +optional
|
||||||
//
|
|
||||||
// This list may not be omitted or empty. If the list contains
|
|
||||||
// "*" then the only other allowed member is "Cluster Scope".
|
|
||||||
// Without "*", it is allowed to list "Cluster Scope" along with
|
|
||||||
// particular namespaces.
|
|
||||||
//
|
|
||||||
// Requests will match only if the values in this list are
|
|
||||||
// appropriate for the resource(s) involved. For example: for a
|
|
||||||
// cluster scoped resource (i.e., one not namespaced) a request
|
|
||||||
// can match only if this list contains "Cluster Scope". It is
|
|
||||||
// entirely up to the client to populate this list with
|
|
||||||
// appropriate values; the server-performed validation does not
|
|
||||||
// (at least in this alpha) address this issue.
|
|
||||||
//
|
|
||||||
// +listType=set
|
// +listType=set
|
||||||
Namespaces []string
|
Namespaces []string
|
||||||
}
|
}
|
||||||
|
@@ -245,20 +245,14 @@ func ValidateFlowSchemaResourcePolicyRule(rule *flowcontrol.ResourcePolicyRule,
|
|||||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("resources"), rule.Resources, "if '*' is present, must not specify other resources"))
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("resources"), rule.Resources, "if '*' is present, must not specify other resources"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rule.Namespaces) == 0 {
|
if len(rule.Namespaces) == 0 && !rule.ClusterScope {
|
||||||
allErrs = append(allErrs, field.Required(fldPath.Child("namespaces"), "resource rules must supply at least one namespace"))
|
allErrs = append(allErrs, field.Required(fldPath.Child("namespaces"), "resource rules that are not cluster scoped must supply at least one namespace"))
|
||||||
} else if memberInList(flowcontrol.NamespaceEvery, rule.Namespaces...) {
|
} else if hasWildcard(rule.Namespaces) {
|
||||||
for _, tgtNS := range rule.Namespaces {
|
if len(rule.Namespaces) > 1 {
|
||||||
if tgtNS != flowcontrol.NamespaceEvery && tgtNS != flowcontrol.NamespaceClusterScope {
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("namespaces"), rule.Namespaces, "if '*' is present, must not specify other namespaces"))
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("namespaces"), rule.Namespaces, "'*' may be accompanied only by 'Cluster Scope'"))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for idx, tgtNS := range rule.Namespaces {
|
for idx, tgtNS := range rule.Namespaces {
|
||||||
if tgtNS == flowcontrol.NamespaceClusterScope {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, msg := range apimachineryvalidation.ValidateNamespaceName(tgtNS, false) {
|
for _, msg := range apimachineryvalidation.ValidateNamespaceName(tgtNS, false) {
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("namespaces").Index(idx), tgtNS, nsErrIntro+msg))
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("namespaces").Index(idx), tgtNS, nsErrIntro+msg))
|
||||||
}
|
}
|
||||||
@@ -268,7 +262,7 @@ func ValidateFlowSchemaResourcePolicyRule(rule *flowcontrol.ResourcePolicyRule,
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
const nsErrIntro = "each member of this list must be '*', 'Cluster Scope', or a DNS-1123 label; "
|
const nsErrIntro = "each member of this list must be '*' or a DNS-1123 label; "
|
||||||
|
|
||||||
// ValidateFlowSchemaStatus validates status for the flow-schema.
|
// ValidateFlowSchemaStatus validates status for the flow-schema.
|
||||||
func ValidateFlowSchemaStatus(status *flowcontrol.FlowSchemaStatus, fldPath *field.Path) field.ErrorList {
|
func ValidateFlowSchemaStatus(status *flowcontrol.FlowSchemaStatus, fldPath *field.Path) field.ErrorList {
|
||||||
|
@@ -407,11 +407,11 @@ func TestFlowSchemaValidation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedErrors: field.ErrorList{
|
expectedErrors: field.ErrorList{
|
||||||
field.Required(field.NewPath("spec").Child("rules").Index(0).Child("resourceRules").Index(0).Child("namespaces"), "resource rules must supply at least one namespace"),
|
field.Required(field.NewPath("spec").Child("rules").Index(0).Child("resourceRules").Index(0).Child("namespaces"), "resource rules that are not cluster scoped must supply at least one namespace"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "NamespaceClusterScope is allowed",
|
name: "ClusterScope is allowed, with no Namespaces",
|
||||||
flowSchema: &flowcontrol.FlowSchema{
|
flowSchema: &flowcontrol.FlowSchema{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "system-foo",
|
Name: "system-foo",
|
||||||
@@ -434,7 +434,7 @@ func TestFlowSchemaValidation(t *testing.T) {
|
|||||||
Verbs: []string{flowcontrol.VerbAll},
|
Verbs: []string{flowcontrol.VerbAll},
|
||||||
APIGroups: []string{flowcontrol.APIGroupAll},
|
APIGroups: []string{flowcontrol.APIGroupAll},
|
||||||
Resources: []string{flowcontrol.ResourceAll},
|
Resources: []string{flowcontrol.ResourceAll},
|
||||||
Namespaces: []string{flowcontrol.NamespaceClusterScope},
|
ClusterScope: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -444,7 +444,7 @@ func TestFlowSchemaValidation(t *testing.T) {
|
|||||||
expectedErrors: field.ErrorList{},
|
expectedErrors: field.ErrorList{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "NamespaceClusterScope is allowed with NamespaceEvery",
|
name: "ClusterScope is allowed with NamespaceEvery",
|
||||||
flowSchema: &flowcontrol.FlowSchema{
|
flowSchema: &flowcontrol.FlowSchema{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "system-foo",
|
Name: "system-foo",
|
||||||
@@ -467,7 +467,8 @@ func TestFlowSchemaValidation(t *testing.T) {
|
|||||||
Verbs: []string{flowcontrol.VerbAll},
|
Verbs: []string{flowcontrol.VerbAll},
|
||||||
APIGroups: []string{flowcontrol.APIGroupAll},
|
APIGroups: []string{flowcontrol.APIGroupAll},
|
||||||
Resources: []string{flowcontrol.ResourceAll},
|
Resources: []string{flowcontrol.ResourceAll},
|
||||||
Namespaces: []string{flowcontrol.NamespaceClusterScope, flowcontrol.NamespaceEvery},
|
ClusterScope: true,
|
||||||
|
Namespaces: []string{flowcontrol.NamespaceEvery},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -508,7 +509,7 @@ func TestFlowSchemaValidation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedErrors: field.ErrorList{
|
expectedErrors: field.ErrorList{
|
||||||
field.Invalid(field.NewPath("spec").Child("rules").Index(0).Child("resourceRules").Index(0).Child("namespaces"), []string{"foo", flowcontrol.NamespaceEvery}, "'*' may be accompanied only by 'Cluster Scope'"),
|
field.Invalid(field.NewPath("spec").Child("rules").Index(0).Child("resourceRules").Index(0).Child("namespaces"), []string{"foo", flowcontrol.NamespaceEvery}, "if '*' is present, must not specify other namespaces"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -29,7 +29,6 @@ const (
|
|||||||
NameAll = "*"
|
NameAll = "*"
|
||||||
|
|
||||||
NamespaceEvery = "*" // matches every particular namespace
|
NamespaceEvery = "*" // matches every particular namespace
|
||||||
NamespaceClusterScope = "Cluster Scope" // matches absence of namespace
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// System preset priority level names
|
// System preset priority level names
|
||||||
@@ -240,31 +239,25 @@ type ResourcePolicyRule struct {
|
|||||||
// +listType=set
|
// +listType=set
|
||||||
Resources []string `json:"resources" protobuf:"bytes,3,rep,name=resources"`
|
Resources []string `json:"resources" protobuf:"bytes,3,rep,name=resources"`
|
||||||
|
|
||||||
|
// `clusterScope` indicates whether to match requests that do not
|
||||||
|
// specify a namespace (which happens either because the resource
|
||||||
|
// is not namespaced or the request targets all namespaces).
|
||||||
|
// If this field is omitted or false then the `namespaces` field
|
||||||
|
// must contain a non-empty list.
|
||||||
|
// +optional
|
||||||
|
ClusterScope bool `json:"clusterScope,omitempty" protobuf:"varint,4,opt,name=clusterScope"`
|
||||||
|
|
||||||
// `namespaces` is a list of target namespaces that restricts
|
// `namespaces` is a list of target namespaces that restricts
|
||||||
// matches. A request that does not specify a target namespace
|
// matches. A request that specifies a target namespace matches
|
||||||
// (which happens both when the resource is not namespaced and
|
// only if either (a) this list contains that target namespace or
|
||||||
// when the resource is namespaced and the request is for all
|
// (b) this list contains "*". Note that "*" matches any
|
||||||
// namespaces) matches only if this list includes "Cluster Scope"
|
// specified namespace but does not match a request that _does
|
||||||
// (this string is not a valid namespace and thus can not be
|
// not specify_ a namespace (see the `clusterScope` field for
|
||||||
// confused with an actual namespace). A request that specifies a
|
// that).
|
||||||
// target namespace matches only if either (a) this list contains
|
// This list may be empty, but only if `clusterScope` is true.
|
||||||
// that target namespace or (b) this list contains "*".
|
// +optional
|
||||||
//
|
|
||||||
// This list may not be omitted or empty. If the list contains
|
|
||||||
// "*" then the only other allowed member is "Cluster Scope".
|
|
||||||
// Without "*", it is allowed to list "Cluster Scope" along with
|
|
||||||
// particular namespaces.
|
|
||||||
//
|
|
||||||
// Requests will match only if the values in this list are
|
|
||||||
// appropriate for the resource(s) involved. For example: for a
|
|
||||||
// cluster scoped resource (i.e., one not namespaced) a request
|
|
||||||
// can match only if this list contains "Cluster Scope". It is
|
|
||||||
// entirely up to the client to populate this list with
|
|
||||||
// appropriate values; the server-performed validation does not
|
|
||||||
// (at least in this alpha) address this issue.
|
|
||||||
//
|
|
||||||
// +listType=set
|
// +listType=set
|
||||||
Namespaces []string `json:"namespaces" protobuf:"bytes,4,rep,name=namespaces"`
|
Namespaces []string `json:"namespaces" protobuf:"bytes,5,rep,name=namespaces"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NonResourcePolicyRule is a predicate that matches non-resource requests according to their verb and the
|
// NonResourcePolicyRule is a predicate that matches non-resource requests according to their verb and the
|
||||||
|
Reference in New Issue
Block a user