Skip to content

Commit 366d9be

Browse files
yuwenmadroot
andauthored
feat: Refactor set-namespace (#785)
Co-authored-by: Sunil Arora <sunilarora@google.com>
1 parent e649e50 commit 366d9be

File tree

10 files changed

+470
-204
lines changed

10 files changed

+470
-204
lines changed
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
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
diff --git a/app.yaml b/app.yaml
2-
index 1f8aeee..33e42da 100644
2+
index d67a0d2..bf55161 100644
33
--- a/app.yaml
44
+++ b/app.yaml
55
@@ -9,7 +9,7 @@ apiVersion: v1
66
kind: Service
77
metadata:
88
name: the-service
9-
- namespace: the-namespace
10-
+ namespace: example-ns
9+
- namespace: example
10+
+ namespace: new-ns
1111
spec:
1212
ports:
1313
- name: etcd-server-ssl
14-
@@ -21,4 +21,4 @@ spec:
14+
@@ -34,4 +34,4 @@ spec:
1515
apiVersion: v1
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/README.md

Lines changed: 91 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,68 +17,114 @@ Namespaces are often used in the following scenarios:
1717

1818
## Usage
1919

20-
This function can be used with any KRM function orchestrators (e.g. kpt).
21-
22-
- If the resource is `Namespace`, `set-namespace` updates the `metadata.name` field.
23-
- If the resource is `RoleBinding` or `ClusterRoleBinding` resource, the function updates
24-
the namespace field in the `subjects` element whose name is `default`.
25-
- If the resource is `CustomResourceDefinition` (CRD), `set-namespace` updates the
26-
`spec/conversion/webhook/clientConfig/service/namespace` field.
27-
- If the resource is `APIService`, `set-namespace` updates the
28-
`spec/service/namespace` field.
29-
- If there is a [`depends-on`] annotation for a namespaced resource, the namespace
30-
section of the annotation will be updated if the referenced resource is also
31-
declared in the package.
20+
This function replaces the KRM resources existing namespace to a new value.
3221

22+
### Target KRM resources
23+
24+
- This function updates all namespace-scoped KRM resources `metadata.namespace` fields.
25+
We determine whether a KRM resource is namespace scoped by checking if it has `metadata.namespace` set and matches the "oldNamespace"
26+
If not, this function won't add new namespace.
27+
- This function updates `RoleBinding` and `ClusterRoleBinding` resources `subjects` element whose kind is `ServiceAccount`
28+
and the subject's `namespace` is set and matches the "oldNamespace".
29+
- This function updates `CustomResourceDefinition` (CRD) `spec/conversion/webhook/clientConfig/service/namespace` field
30+
if the field is set and matches the "oldNamespace"
31+
- This function updates `APIService` `spec/service/namespace` field if the field is set and matches the "oldNamespace"
32+
- This function updates the KRM resources annotation `config.kubernetes.io/depends-on` if this annotation contains the
33+
matching namespace.
34+
35+
### FunctionConfig
36+
37+
This function supports the default `ConfigMap` as function config and a custom `SetNamespace`. See below examples
38+
39+
`ConfigMap` as functionConfig
3340
```yaml
3441
apiVersion: v1
35-
kind: ServiceAccount
36-
metadata:
37-
name: sa
38-
namespace: example
39-
annotations:
40-
config.kubernetes.io/depends-on: /namespaces/example/ServiceAccount/foo # <= this will NOT be updated (resource not declared)
41-
---
42-
kind: RoleBinding
43-
apiVersion: rbac.authorization.k8s.io/v1
44-
metadata:
45-
...
46-
annotations:
47-
config.kubernetes.io/depends-on: /namespaces/example/ServiceAccount/sa # <== this will be updated (resource declared)
48-
subjects:
49-
- kind: ServiceAccount
50-
name: default # <================== name default is used
51-
namespace: example # <================== this will be updated
52-
roleRef:
53-
kind: Role
54-
name: confluent-operator
55-
apiGroup: rbac.authorization.k8s.io
42+
kind: ConfigMap
43+
data:
44+
namespace: newNamespace # required
45+
namespaceMatcher: example # update namespace whose value is "example" to "newNamespace"
5646
```
5747
58-
This function can be used both declaratively and imperatively.
48+
`SetNamespace` as functionConfig
49+
```yaml
50+
apiVersion: fn.kpt.dev/v1alpha1
51+
kind: SetNamespace
52+
namespace: newNamespace # required
53+
namespaceMatcher: example # update namespace whose value is "example" to "newNamespace"
54+
```
5955

60-
### FunctionConfig
6156

62-
There are 2 kinds of `functionConfig` supported by this function:
57+
### Three updating modes
6358

64-
- `ConfigMap`
65-
- A custom resource of kind `SetNamespace`
59+
This function supports three modes to flexibly choose and update the target namespaces.
6660

67-
To use a `ConfigMap` as the `functionConfig`, the desired namespace must be
68-
specified in the `data.namespace` field.
61+
##### Restrict Mode
62+
All target KRM resources namespace has to have the same value. All namespace will be updated to the new value.
6963

70-
To add a namespace `staging` to all resources, we use the
71-
following `functionConfig`:
64+
`ConfigMap` as functionConfig
65+
```yaml
66+
apiVersion: v1
67+
kind: ConfigMap
68+
data:
69+
namespace: newNamespace # update all namespace fields to "newNamespace"
70+
```
71+
72+
##### DefaultNamespace Mode
73+
74+
The input `resourcelist.items` contains one and only one `Namespace` object. The function matches the namespace `metadata.name`
75+
with all other KRM resources, and only update the namespace if it matches the `Namespace` object.
76+
If more than one `Namespace` objects are found, raise errors;
7277

78+
```yaml
79+
kind: ResourceList
80+
functionConfig:
81+
apiVersion: v1
82+
kind: ConfigMap
83+
data:
84+
namespace: newNs
85+
items:
86+
- apiVersion: v1
87+
kind: Namespace
88+
metadata:
89+
name: example # updated to "newNs"
90+
- apiVersion: v1
91+
kind: Service
92+
metadata:
93+
name: the-service1
94+
namespace: example # updated to "newNs"
95+
- apiVersion: v1
96+
kind: Service
97+
metadata:
98+
name: the-service2
99+
namespace: irrelevant # skip since namespace does not match "example".
100+
```
101+
102+
##### Matcher Mode
103+
104+
Only updates the namespace which matches a given value. The "oldNamespace" refers to the argument in FunctionConfig
105+
106+
`ConfigMap` as functionConfig
73107
```yaml
74108
apiVersion: v1
75109
kind: ConfigMap
76-
metadata:
77-
name: my-config
78110
data:
79-
namespace: staging
111+
namespace: newNamespace
112+
namespaceMatcher: example # update namespace whose value is "example" to "newNamespace"
113+
```
114+
115+
`SetNamespace` as functionConfig
116+
```yaml
117+
apiVersion: fn.kpt.dev/v1alpha1
118+
kind: SetNamespace
119+
namespace: newNamespace
120+
namespaceMatcher: example # update namespace whose value is "example" to "newNamespace"
80121
```
81122

123+
### DependsOn annotation
124+
125+
DependsOn annotation is a [kpt feature](https://kpt.dev/reference/annotations/depends-on/). This function updates the
126+
namespace segment in a depends-on annotation if the namespace matches the `Namespace` object or `namespaceMatcher` field.
127+
82128
<!--mdtogo-->
83129

84130
[namespace]: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/

functions/go/set-namespace/generated/docs.go

Lines changed: 83 additions & 47 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)