mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-07-18 02:01:29 +00:00
Force the namespace value for the "default" service object.
The clusterrolebinding and rolebinding is pointing at a resource which is not listed in the kustomize
This commit is contained in:
@@ -159,6 +159,9 @@ subjects:
|
|||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: sa3
|
name: sa3
|
||||||
namespace: random
|
namespace: random
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: irrelevant
|
||||||
---
|
---
|
||||||
apiVersion: admissionregistration.k8s.io/v1beta1
|
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||||
kind: ValidatingWebhookConfiguration
|
kind: ValidatingWebhookConfiguration
|
||||||
@@ -193,6 +196,10 @@ metadata:
|
|||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
name: crb1
|
name: crb1
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: irrelevant
|
||||||
---
|
---
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
@@ -254,6 +261,9 @@ subjects:
|
|||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: sa3
|
name: sa3
|
||||||
namespace: random
|
namespace: random
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: newnamespace
|
||||||
---
|
---
|
||||||
apiVersion: admissionregistration.k8s.io/v1beta1
|
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||||
kind: ValidatingWebhookConfiguration
|
kind: ValidatingWebhookConfiguration
|
||||||
@@ -288,6 +298,10 @@ metadata:
|
|||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
name: p1-crb1-s1
|
name: p1-crb1-s1
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: newnamespace
|
||||||
---
|
---
|
||||||
kind: PersistentVolume
|
kind: PersistentVolume
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
@@ -21,5 +21,9 @@ const (
|
|||||||
namespace:
|
namespace:
|
||||||
- path: metadata/namespace
|
- path: metadata/namespace
|
||||||
create: true
|
create: true
|
||||||
|
- path: subjects
|
||||||
|
kind: RoleBinding
|
||||||
|
- path: subjects
|
||||||
|
kind: ClusterRoleBinding
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -35,17 +35,19 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, r := range m.Resources() {
|
for _, r := range m.Resources() {
|
||||||
id := r.OrgId()
|
|
||||||
fs, ok := p.isSelected(id)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(r.Map()) == 0 {
|
if len(r.Map()) == 0 {
|
||||||
// Don't mutate empty objects?
|
// Don't mutate empty objects?
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if doIt(id, fs) {
|
|
||||||
if err := p.changeNamespace(r, fs); err != nil {
|
id := r.OrgId()
|
||||||
|
applicableFs := p.applicableFieldSpecs(id)
|
||||||
|
|
||||||
|
for _, fs := range applicableFs {
|
||||||
|
err := transformers.MutateField(
|
||||||
|
r.Map(), fs.PathSlice(), fs.CreateIfNotPresent,
|
||||||
|
p.changeNamespace(r))
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,26 +61,64 @@ const metaNamespace = "metadata/namespace"
|
|||||||
// all objects have it, even "ClusterKind" objects
|
// all objects have it, even "ClusterKind" objects
|
||||||
// that don't exist in a namespace (the Namespace
|
// that don't exist in a namespace (the Namespace
|
||||||
// object itself doesn't live in a namespace).
|
// object itself doesn't live in a namespace).
|
||||||
func doIt(id resid.ResId, fs *config.FieldSpec) bool {
|
func (p *NamespaceTransformerPlugin) applicableFieldSpecs(id resid.ResId) []config.FieldSpec {
|
||||||
return fs.Path != metaNamespace ||
|
res := []config.FieldSpec{}
|
||||||
(fs.Path == metaNamespace && id.IsNamespaceableKind())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *NamespaceTransformerPlugin) changeNamespace(
|
|
||||||
r *resource.Resource, fs *config.FieldSpec) error {
|
|
||||||
return transformers.MutateField(
|
|
||||||
r.Map(), fs.PathSlice(), fs.CreateIfNotPresent,
|
|
||||||
func(_ interface{}) (interface{}, error) {
|
|
||||||
return p.Namespace, nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *NamespaceTransformerPlugin) isSelected(
|
|
||||||
id resid.ResId) (*config.FieldSpec, bool) {
|
|
||||||
for _, fs := range p.FieldSpecs {
|
for _, fs := range p.FieldSpecs {
|
||||||
if id.IsSelected(&fs.Gvk) {
|
if id.IsSelected(&fs.Gvk) && (fs.Path != metaNamespace || (fs.Path == metaNamespace && id.IsNamespaceableKind())) {
|
||||||
return &fs, true
|
res = append(res, fs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *NamespaceTransformerPlugin) changeNamespace(
|
||||||
|
referrer *resource.Resource) func(in interface{}) (interface{}, error) {
|
||||||
|
return func(in interface{}) (interface{}, error) {
|
||||||
|
switch in.(type) {
|
||||||
|
case string:
|
||||||
|
// will happen when the metadata/namespace
|
||||||
|
// value is replaced
|
||||||
|
return o.Namespace, nil
|
||||||
|
case []interface{}:
|
||||||
|
l, _ := in.([]interface{})
|
||||||
|
for idx, item := range l {
|
||||||
|
switch item.(type) {
|
||||||
|
case map[string]interface{}:
|
||||||
|
// Will happen when mutating the subjects
|
||||||
|
// field of ClusterRoleBinding and RoleBinding
|
||||||
|
inMap, _ := item.(map[string]interface{})
|
||||||
|
if _, ok := inMap["name"]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name, ok := inMap["name"].(string)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// The only case we need to force the namespace
|
||||||
|
// if for the "service account". "default" is
|
||||||
|
// kind of hardcoded here for right now.
|
||||||
|
if name != "default" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
inMap["namespace"] = o.Namespace
|
||||||
|
l[idx] = inMap
|
||||||
|
default:
|
||||||
|
// nothing to do for right now
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return in, nil
|
||||||
|
case map[string]interface{}:
|
||||||
|
// Will happen if the createField=true
|
||||||
|
// when the namespace is added to the
|
||||||
|
// object
|
||||||
|
inMap := in.(map[string]interface{})
|
||||||
|
if len(inMap) == 0 {
|
||||||
|
return o.Namespace, nil
|
||||||
|
} else {
|
||||||
|
return in, nil
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return in, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, false
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,17 +36,19 @@ func (p *plugin) Transform(m resmap.ResMap) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, r := range m.Resources() {
|
for _, r := range m.Resources() {
|
||||||
id := r.OrgId()
|
|
||||||
fs, ok := p.isSelected(id)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(r.Map()) == 0 {
|
if len(r.Map()) == 0 {
|
||||||
// Don't mutate empty objects?
|
// Don't mutate empty objects?
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if doIt(id, fs) {
|
|
||||||
if err := p.changeNamespace(r, fs); err != nil {
|
id := r.OrgId()
|
||||||
|
applicableFs := p.applicableFieldSpecs(id)
|
||||||
|
|
||||||
|
for _, fs := range applicableFs {
|
||||||
|
err := transformers.MutateField(
|
||||||
|
r.Map(), fs.PathSlice(), fs.CreateIfNotPresent,
|
||||||
|
p.changeNamespace(r))
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,26 +62,64 @@ const metaNamespace = "metadata/namespace"
|
|||||||
// all objects have it, even "ClusterKind" objects
|
// all objects have it, even "ClusterKind" objects
|
||||||
// that don't exist in a namespace (the Namespace
|
// that don't exist in a namespace (the Namespace
|
||||||
// object itself doesn't live in a namespace).
|
// object itself doesn't live in a namespace).
|
||||||
func doIt(id resid.ResId, fs *config.FieldSpec) bool {
|
func (p *plugin) applicableFieldSpecs(id resid.ResId) []config.FieldSpec {
|
||||||
return fs.Path != metaNamespace ||
|
res := []config.FieldSpec{}
|
||||||
(fs.Path == metaNamespace && id.IsNamespaceableKind())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *plugin) changeNamespace(
|
|
||||||
r *resource.Resource, fs *config.FieldSpec) error {
|
|
||||||
return transformers.MutateField(
|
|
||||||
r.Map(), fs.PathSlice(), fs.CreateIfNotPresent,
|
|
||||||
func(_ interface{}) (interface{}, error) {
|
|
||||||
return p.Namespace, nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *plugin) isSelected(
|
|
||||||
id resid.ResId) (*config.FieldSpec, bool) {
|
|
||||||
for _, fs := range p.FieldSpecs {
|
for _, fs := range p.FieldSpecs {
|
||||||
if id.IsSelected(&fs.Gvk) {
|
if id.IsSelected(&fs.Gvk) && (fs.Path != metaNamespace || (fs.Path == metaNamespace && id.IsNamespaceableKind())) {
|
||||||
return &fs, true
|
res = append(res, fs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *plugin) changeNamespace(
|
||||||
|
referrer *resource.Resource) func(in interface{}) (interface{}, error) {
|
||||||
|
return func(in interface{}) (interface{}, error) {
|
||||||
|
switch in.(type) {
|
||||||
|
case string:
|
||||||
|
// will happen when the metadata/namespace
|
||||||
|
// value is replaced
|
||||||
|
return o.Namespace, nil
|
||||||
|
case []interface{}:
|
||||||
|
l, _ := in.([]interface{})
|
||||||
|
for idx, item := range l {
|
||||||
|
switch item.(type) {
|
||||||
|
case map[string]interface{}:
|
||||||
|
// Will happen when mutating the subjects
|
||||||
|
// field of ClusterRoleBinding and RoleBinding
|
||||||
|
inMap, _ := item.(map[string]interface{})
|
||||||
|
if _, ok := inMap["name"]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name, ok := inMap["name"].(string)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// The only case we need to force the namespace
|
||||||
|
// if for the "service account". "default" is
|
||||||
|
// kind of hardcoded here for right now.
|
||||||
|
if name != "default" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
inMap["namespace"] = o.Namespace
|
||||||
|
l[idx] = inMap
|
||||||
|
default:
|
||||||
|
// nothing to do for right now
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return in, nil
|
||||||
|
case map[string]interface{}:
|
||||||
|
// Will happen if the createField=true
|
||||||
|
// when the namespace is added to the
|
||||||
|
// object
|
||||||
|
inMap := in.(map[string]interface{})
|
||||||
|
if len(inMap) == 0 {
|
||||||
|
return o.Namespace, nil
|
||||||
|
} else {
|
||||||
|
return in, nil
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return in, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, false
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,12 @@ metadata:
|
|||||||
fieldSpecs:
|
fieldSpecs:
|
||||||
- path: metadata/namespace
|
- path: metadata/namespace
|
||||||
create: true
|
create: true
|
||||||
|
- path: subjects
|
||||||
|
kind: RoleBinding
|
||||||
|
group: rbac.authorization.k8s.io
|
||||||
|
- path: subjects
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
group: rbac.authorization.k8s.io
|
||||||
`, `
|
`, `
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
@@ -54,7 +60,7 @@ apiVersion: v1
|
|||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
name: default
|
name: default
|
||||||
namespace: system
|
namespace: test
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
@@ -151,7 +157,7 @@ metadata:
|
|||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: default
|
name: default
|
||||||
namespace: system
|
namespace: test
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: service-account
|
name: service-account
|
||||||
namespace: system
|
namespace: system
|
||||||
@@ -222,6 +228,12 @@ metadata:
|
|||||||
fieldSpecs:
|
fieldSpecs:
|
||||||
- path: metadata/namespace
|
- path: metadata/namespace
|
||||||
create: true
|
create: true
|
||||||
|
- path: subjects
|
||||||
|
kind: RoleBinding
|
||||||
|
group: rbac.authorization.k8s.io
|
||||||
|
- path: subjects
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
group: rbac.authorization.k8s.io
|
||||||
`, noChangeExpected)
|
`, noChangeExpected)
|
||||||
|
|
||||||
th.AssertActualEqualsExpected(rm, noChangeExpected)
|
th.AssertActualEqualsExpected(rm, noChangeExpected)
|
||||||
|
|||||||
Reference in New Issue
Block a user