Skip to content

Commit fcba72c

Browse files
committed
Use GetSlice and get/set by string pointer.
merge after
1 parent b9aec2a commit fcba72c

8 files changed

Lines changed: 125 additions & 94 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
testType: eval
22
image: gcr.io/kpt-fn/set-namespace:unstable
33
args:
4-
namespace: example-ns
4+
namespace: new-ns

examples/set-namespace-imperative/.expected/diff.patch

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ index 1f8aeee..33e42da 100644
77
metadata:
88
name: the-service
99
- namespace: the-namespace
10-
+ namespace: example-ns
10+
+ namespace: new-ns
1111
spec:
1212
ports:
1313
- name: etcd-server-ssl
@@ -16,4 +16,4 @@ index 1f8aeee..33e42da 100644
1616
kind: Namespace
1717
metadata:
1818
- name: example
19-
+ name: example-ns
19+
+ name: new-ns

examples/set-namespace-imperative/README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
### Overview
44

5-
This examples shows how to set namespace in the `.metadata.namespace` field on
6-
all resources by running [`set-namespace`] function imperatively. Resources that
7-
are known to be cluster-scoped will be skipped.
5+
This examples shows how to replace KRM resources' namespace fields by matching
6+
the namespace with the namespace object's `metadata.name`.
7+
The example uses `kpt fn eval` to run the function imperatively.
88

99
### Fetch the example package
1010

@@ -27,6 +27,7 @@ The desired namespace is provided after `--` and it will be converted to
2727

2828
### Expected result
2929

30-
Check all resources have `metadata.namespace` set to `example-ns`:
30+
Only the namespace fields which match the `namespace` "example" object has the value updated to
31+
`new-ns`:
3132

3233
[`set-namespace`]: https://catalog.kpt.dev/set-namespace/v0.1/

examples/set-namespace-imperative/app.yaml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,20 @@ apiVersion: v1
99
kind: Service
1010
metadata:
1111
name: the-service
12-
namespace: the-namespace
12+
namespace: example
13+
spec:
14+
ports:
15+
- name: etcd-server-ssl
16+
port: 2380
17+
- name: etcd-client-ssl
18+
port: 2379
19+
publishNotReadyAddresses: true
20+
---
21+
apiVersion: v1
22+
kind: Service
23+
metadata:
24+
name: the-service
25+
namespace: not-match-example
1326
spec:
1427
ports:
1528
- name: etcd-server-ssl

functions/go/set-namespace/Dockerfile

Lines changed: 0 additions & 17 deletions
This file was deleted.

functions/go/set-namespace/go.mod

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,34 @@ module github.com/GoogleContainerTools/kpt-functions-catalog/functions/go/set-na
33
go 1.17
44

55
require (
6-
github.com/GoogleContainerTools/kpt-functions-sdk/go/fn v0.0.0-20220326221816-442298f7a17c
6+
github.com/GoogleContainerTools/kpt-functions-sdk/go/fn v0.0.0-20220405020624-e5817d5d2014
77
k8s.io/apimachinery v0.23.5
88
)
99

1010
require (
1111
github.com/PuerkitoBio/purell v1.1.1 // indirect
1212
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
1313
github.com/davecgh/go-spew v1.1.1 // indirect
14-
github.com/go-errors/errors v1.0.1 // indirect
15-
github.com/go-logr/logr v1.2.0 // indirect
14+
github.com/go-errors/errors v1.4.2 // indirect
15+
github.com/go-logr/logr v1.2.3 // indirect
1616
github.com/go-openapi/jsonpointer v0.19.5 // indirect
17-
github.com/go-openapi/jsonreference v0.19.3 // indirect
18-
github.com/go-openapi/swag v0.19.5 // indirect
19-
github.com/mailru/easyjson v0.7.0 // indirect
17+
github.com/go-openapi/jsonreference v0.19.6 // indirect
18+
github.com/go-openapi/swag v0.21.1 // indirect
19+
github.com/golang/protobuf v1.5.2 // indirect
20+
github.com/google/gnostic v0.6.7 // indirect
21+
github.com/josharian/intern v1.0.0 // indirect
22+
github.com/mailru/easyjson v0.7.7 // indirect
2023
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
2124
github.com/pkg/errors v0.9.1 // indirect
2225
github.com/pmezard/go-difflib v1.0.0 // indirect
23-
github.com/stretchr/testify v1.7.0 // indirect
24-
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
25-
golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
26+
github.com/stretchr/testify v1.7.1 // indirect
27+
github.com/xlab/treeprint v1.1.0 // indirect
28+
golang.org/x/net v0.0.0-20220403103023-749bd193bc2b // indirect
2629
golang.org/x/text v0.3.7 // indirect
30+
google.golang.org/protobuf v1.28.0 // indirect
2731
gopkg.in/yaml.v2 v2.4.0 // indirect
2832
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
29-
k8s.io/klog/v2 v2.30.0 // indirect
30-
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
31-
sigs.k8s.io/kustomize/kyaml v0.13.3 // indirect
33+
k8s.io/klog/v2 v2.60.1 // indirect
34+
k8s.io/kube-openapi v0.0.0-20220401212409-b28bf2818661 // indirect
35+
sigs.k8s.io/kustomize/kyaml v0.13.6 // indirect
3236
)

functions/go/set-namespace/go.sum

Lines changed: 53 additions & 13 deletions
Large diffs are not rendered by default.

functions/go/set-namespace/transformer/namespace.go

Lines changed: 34 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ import (
2222
"k8s.io/apimachinery/pkg/util/sets"
2323
)
2424

25-
func SetNamespace(rl *fn.ResourceList) error {
25+
func SetNamespace(rl *fn.ResourceList) (bool, error) {
2626
tc := NamespaceTransformer{}
2727
// Get "namespace" arguments from FunctionConfig
2828
err := tc.Config(rl.FunctionConfig)
2929
if err != nil {
3030
rl.Results = append(rl.Results, fn.ErrorConfigObjectResult(err, rl.FunctionConfig))
31-
return nil
31+
return true, nil
3232
}
3333
// Update "namespace" to the proper resources.
3434
tc.Transform(rl.Items)
@@ -40,7 +40,7 @@ func SetNamespace(rl *fn.ResourceList) error {
4040
result = fn.GeneralResult("namespace updated", fn.Info)
4141
}
4242
rl.Results = append(rl.Results, result)
43-
return nil
43+
return true, nil
4444
}
4545

4646
// Config gets the attributes from different FunctionConfig formats.
@@ -84,43 +84,42 @@ func (p *NamespaceTransformer) Transform(objects []*fn.KubeObject) {
8484
}
8585
}
8686

87-
// VisitNamespaces iterates the `objects` to execute the `callback` function on each corresponding namespace field.
88-
func VisitNamespaces(objects []*fn.KubeObject, callback func(ns *Namespace)) {
87+
// VisitNamespaces iterates the `objects` to execute the `visitor` function on each corresponding namespace field.
88+
func VisitNamespaces(objects []*fn.KubeObject, visitor func(namespace *Namespace)) {
8989
for _, o := range objects {
9090
switch {
9191
// Skip local resource which `kpt live apply` skips.
9292
case o.IsLocalConfig():
9393
continue
9494
case o.IsGVK("v1", "Namespace"):
95-
ns := NewNamespace(o, []string{"metadata", "name"})
96-
callback(ns)
95+
namespace := o.GetStringOrDie("metadata", "name")
96+
visitor(NewNamespace(o, &namespace))
97+
o.SetOrDie(&namespace, "metadata", "name")
9798
case o.IsGVK("apiextensions.k8s.io/v1", "CustomResourceDefinition"):
98-
fields := []string{"spec", "conversion", "webhook", "clientConfig", "service", "namespace"}
99-
callback(NewNamespace(o, fields))
99+
namespace := o.GetStringOrDie("spec", "conversion", "webhook", "clientConfig", "service", "namespace")
100+
visitor(NewNamespace(o, &namespace))
101+
o.SetOrDie(&namespace, "spec", "conversion", "webhook", "clientConfig", "service", "namespace")
100102
case o.IsGVK("apiregistration.k8s.io/v1", "APIService"):
101-
fields := []string{"spec", "service", "namespace"}
102-
callback(NewNamespace(o, fields))
103-
/* TODO(yuwenma): waiting for the new features in kpt-functions-sdk to merge in.
103+
namespace := o.GetStringOrDie("spec", "service", "namespace")
104+
visitor(NewNamespace(o, &namespace))
105+
o.SetOrDie(&namespace, "spec", "service", "namespace")
104106
case o.GetKind() == "ClusterRoleBinding" || o.GetKind() == "RoleBinding":
105-
subjects := o.GetSliceOrDie("subjects")
106-
for _, s := range subjects {
107-
if s.GetKind() == "ServiceAccount" {
108-
ns := s.GetNamespace()
109-
visitor(ns, false)
110-
nsCollector <- func() {
111-
nsPtr := &ns
112-
p.updateNamespace(nsPtr)
113-
s.SetNamespace(*nsPtr)
114-
o.SetOrDie(&subjects, "subjects")
107+
subjects := o.GetSlice("subjects")
108+
for _, s := range subjects {
109+
var ns string
110+
found, _ := s.Get(&ns, "namespace")
111+
if found {
112+
visitor(NewNamespace(o, &ns))
113+
_ = s.Set(&ns, "namespace")
115114
}
116115
}
117-
}
118-
*/
116+
o.SetOrDie(&subjects, "subjects")
119117
case o.HasNamespace():
120118
// Only update the namespace scoped resource. To determine if a resource is namespace scoped,
121119
// we assume its namespace should have been set.
122-
fields := []string{"metadata", "namespace"}
123-
callback(NewNamespace(o, fields))
120+
namespace := o.GetStringOrDie("metadata", "namespace")
121+
visitor(NewNamespace(o, &namespace))
122+
o.SetOrDie(&namespace, "metadata", "namespace")
124123
default:
125124
// skip the cluster scoped resource. We determine if a resource is cluster scoped by
126125
// checking if the metadata.namespace is configured.
@@ -133,25 +132,25 @@ func FindAllNamespaces(objects []*fn.KubeObject) ([]string, map[string]int) {
133132
nsObjCounter := map[string]int{}
134133
namespaces := sets.NewString()
135134
VisitNamespaces(objects, func(ns *Namespace) {
136-
if ns.Name == "" {
135+
if *ns.Ptr == "" {
137136
return
138137
}
139138
if ns.IsNamespace {
140-
nsObjCounter[ns.Name] += 1
139+
nsObjCounter[*ns.Ptr] += 1
141140
}
142-
namespaces.Insert(ns.Name)
141+
namespaces.Insert(*ns.Ptr)
143142
})
144143
return namespaces.List(), nsObjCounter
145144
}
146145

147146
// ReplaceNamespace iterates the `objects` to replace the `OldNs` with `newNs` on namespace field.
148147
func ReplaceNamespace(objects []*fn.KubeObject, oldNs, newNs string) {
149148
VisitNamespaces(objects, func(ns *Namespace) {
150-
if ns.Name == "" {
149+
if *ns.Ptr == "" {
151150
return
152151
}
153-
if ns.Name == oldNs {
154-
ns.Set(newNs)
152+
if *ns.Ptr == oldNs {
153+
*ns.Ptr = newNs
155154
}
156155
})
157156
}
@@ -232,10 +231,7 @@ type NamespaceTransformer struct {
232231
Errors []string
233232
}
234233

235-
func NewNamespace(obj *fn.KubeObject, path []string) *Namespace {
236-
setter := func(newNs string) {
237-
_ = obj.Set(newNs, path...)
238-
}
234+
func NewNamespace(obj *fn.KubeObject, namespacePtr *string) *Namespace {
239235
annotationSetter := func(newAnnotation string) {
240236
obj.SetAnnotation(dependsOnAnnotation, newAnnotation)
241237
}
@@ -247,28 +243,22 @@ func NewNamespace(obj *fn.KubeObject, path []string) *Namespace {
247243
return dependsOnKeyPattern(group, obj.GetKind(), obj.GetName())
248244
}
249245
return &Namespace{
250-
Name: obj.GetStringOrDie(path...),
246+
Ptr: namespacePtr, // obj.GetStringOrDie(path...),
251247
IsNamespace: obj.IsGVK("v1", "Namespace"),
252248
DependsOnAnnotation: obj.GetAnnotations()[dependsOnAnnotation],
253-
setter: setter,
254249
annotationGetter: annotationGetter,
255250
annotationSetter: annotationSetter,
256251
}
257252
}
258253

259254
type Namespace struct {
260-
Name string
255+
Ptr *string
261256
IsNamespace bool
262257
DependsOnAnnotation string
263-
setter func(newNs string)
264258
annotationGetter func() string
265259
annotationSetter func(newDependsOnAnnotation string)
266260
}
267261

268-
func (n *Namespace) Set(newNs string) {
269-
n.setter(newNs)
270-
}
271-
272262
func (n *Namespace) SetDependsOnAnnotation(newDependsOn string) {
273263
n.annotationSetter(newDependsOn)
274264
}

0 commit comments

Comments
 (0)