mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-17 18:25:26 +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
|
||||
name: sa3
|
||||
namespace: random
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: irrelevant
|
||||
---
|
||||
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||
kind: ValidatingWebhookConfiguration
|
||||
@@ -193,6 +196,10 @@ metadata:
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: crb1
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: irrelevant
|
||||
---
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
@@ -254,6 +261,9 @@ subjects:
|
||||
- kind: ServiceAccount
|
||||
name: sa3
|
||||
namespace: random
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: newnamespace
|
||||
---
|
||||
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||
kind: ValidatingWebhookConfiguration
|
||||
@@ -288,6 +298,10 @@ metadata:
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: p1-crb1-s1
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: newnamespace
|
||||
---
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
|
||||
@@ -21,5 +21,9 @@ const (
|
||||
namespace:
|
||||
- path: metadata/namespace
|
||||
create: true
|
||||
- path: subjects
|
||||
kind: RoleBinding
|
||||
- path: subjects
|
||||
kind: ClusterRoleBinding
|
||||
`
|
||||
)
|
||||
|
||||
@@ -35,17 +35,19 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||
return nil
|
||||
}
|
||||
for _, r := range m.Resources() {
|
||||
id := r.OrgId()
|
||||
fs, ok := p.isSelected(id)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if len(r.Map()) == 0 {
|
||||
// Don't mutate empty objects?
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -59,26 +61,64 @@ const metaNamespace = "metadata/namespace"
|
||||
// all objects have it, even "ClusterKind" objects
|
||||
// that don't exist in a namespace (the Namespace
|
||||
// object itself doesn't live in a namespace).
|
||||
func doIt(id resid.ResId, fs *config.FieldSpec) bool {
|
||||
return fs.Path != metaNamespace ||
|
||||
(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) {
|
||||
func (p *NamespaceTransformerPlugin) applicableFieldSpecs(id resid.ResId) []config.FieldSpec {
|
||||
res := []config.FieldSpec{}
|
||||
for _, fs := range p.FieldSpecs {
|
||||
if id.IsSelected(&fs.Gvk) {
|
||||
return &fs, true
|
||||
if id.IsSelected(&fs.Gvk) && (fs.Path != metaNamespace || (fs.Path == metaNamespace && id.IsNamespaceableKind())) {
|
||||
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
|
||||
}
|
||||
for _, r := range m.Resources() {
|
||||
id := r.OrgId()
|
||||
fs, ok := p.isSelected(id)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if len(r.Map()) == 0 {
|
||||
// Don't mutate empty objects?
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -60,26 +62,64 @@ const metaNamespace = "metadata/namespace"
|
||||
// all objects have it, even "ClusterKind" objects
|
||||
// that don't exist in a namespace (the Namespace
|
||||
// object itself doesn't live in a namespace).
|
||||
func doIt(id resid.ResId, fs *config.FieldSpec) bool {
|
||||
return fs.Path != metaNamespace ||
|
||||
(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) {
|
||||
func (p *plugin) applicableFieldSpecs(id resid.ResId) []config.FieldSpec {
|
||||
res := []config.FieldSpec{}
|
||||
for _, fs := range p.FieldSpecs {
|
||||
if id.IsSelected(&fs.Gvk) {
|
||||
return &fs, true
|
||||
if id.IsSelected(&fs.Gvk) && (fs.Path != metaNamespace || (fs.Path == metaNamespace && id.IsNamespaceableKind())) {
|
||||
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:
|
||||
- path: metadata/namespace
|
||||
create: true
|
||||
- path: subjects
|
||||
kind: RoleBinding
|
||||
group: rbac.authorization.k8s.io
|
||||
- path: subjects
|
||||
kind: ClusterRoleBinding
|
||||
group: rbac.authorization.k8s.io
|
||||
`, `
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
@@ -54,7 +60,7 @@ apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: default
|
||||
namespace: system
|
||||
namespace: test
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
@@ -151,7 +157,7 @@ metadata:
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: system
|
||||
namespace: test
|
||||
- kind: ServiceAccount
|
||||
name: service-account
|
||||
namespace: system
|
||||
@@ -222,6 +228,12 @@ metadata:
|
||||
fieldSpecs:
|
||||
- path: metadata/namespace
|
||||
create: true
|
||||
- path: subjects
|
||||
kind: RoleBinding
|
||||
group: rbac.authorization.k8s.io
|
||||
- path: subjects
|
||||
kind: ClusterRoleBinding
|
||||
group: rbac.authorization.k8s.io
|
||||
`, noChangeExpected)
|
||||
|
||||
th.AssertActualEqualsExpected(rm, noChangeExpected)
|
||||
|
||||
Reference in New Issue
Block a user