github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/docs/design-docs/05-kpt-fn-exclude.md (about) 1 # Title 2 3 * Author(s): Natasha Sarkar, natasha41575 4 * Approver: Sunil Arora, droot 5 6 ## Why 7 8 `kpt fn render` and `kpt fn eval` now include meta resources (functionConfigs and the Kptfile), 9 a breaking change from previous behavior. Users who use functions such as set-labels and set-namespace 10 will now see their KRM functions acting on resources that were previously excluded by default. 11 For these users, we need to provide a way to preserve old behavior by introducing a mechanism to 12 exclude certain resources, such as resources of a certain GVK or local configuration resources, from 13 being acted on by kpt functions during `kpt fn render` and `kpt fn eval`. 14 15 ### Background 16 17 Open source issue: https://github.com/GoogleContainerTools/kpt/issues/2930 18 19 #### Redefining and inclusion of meta resources 20 21 Previously, `kpt fn render` and `kpt fn eval` excluded functionConfigs and the Kptfile. A user could include t 22 hese "meta resources'' by setting the `--include-meta-resources` flag. There is a separate discussion 23 and PR (https://github.com/GoogleContainerTools/kpt/pull/2894) with the following changes: 24 25 - The definition of meta-resources. Kpt no longer considers functionConfigs as meta resources; they are KRM 26 resources like any other, and the fact that they are used to configure a KRM function does not mean they should be 27 treated specially. With this change, "meta-resources" only includes the Kptfile. 28 - The `--include-meta-resources` flag is going away, and meta resources are processed by all kpt functions by default. 29 With this change, there is no mechanism for users to exclude the Kptfile. 30 31 #### `kpt fn` selectors 32 33 kpt fn render and kpt fn eval currently support selector-based mechanisms to target certain resources. 34 35 Imperatively: 36 37 ```shell 38 $ kpt fn eval [PKG_DIR] -i set-labels:v0.1.5 --match-kind Deployment 39 ``` 40 41 Declaratively: 42 43 ```yaml 44 # pipeline of Kptfile 45 pipeline: 46 mutators: 47 - image: set-labels:v0.1.5 48 selectors: 49 - kind: Deployment 50 ``` 51 52 These selectors only allow you to list out which resources you want to include. There is no current mechanism to exclude a certain kind of resource. 53 For example, the user may want to exclude the Kptfile. 54 55 #### Prior art in kustomize 56 The kustomize `replacements` feature (used in our new apply-replacements function), allows a mechanism to exclude certain resources from being modified. 57 `replacements` is one of the most popular among kustomize users. 58 59 Kustomize has also had a few requests (such as this one: https://github.com/kubernetes/enhancements/pull/1232) to allow transformers to skip resources of a 60 certain GVK, which gives us confidence that a similar feature in kpt would be welcome. 61 62 ## Design 63 64 ### A new `exclude` option inline with selectors 65 66 We can extend the current selector mechanism to allow exclusions. This can be achieved by new exclude flags for imperative workflow and a new exclude field in the 67 Kptfile pipeline for declarative workflow. These correspond to the imperative match flags and declarative selectors field. 68 69 A few reasons in favor of this design: 70 - Flexible and powerful 71 - Allows users very explicit control of which resources are included at a per-function level 72 - It is consistent with our current selector mechanism. 73 - It is consistent with the syntax of kustomize replacements (used in our new apply-replacements function), which is popular and heavily used among the kubernetes community 74 - It is consistent with a highly requested feature in kustomize to allow transformers to exclude resources of a certain GVK. 75 76 #### Example: Exclude all resources of kind "Deployment" 77 78 ```shell 79 $ kpt fn eval [PKG_DIR] -i set-labels:v0.1.5 --exclude-kind Deployment 80 ``` 81 82 ```yaml 83 # pipeline of Kptfile 84 pipeline: 85 mutators: 86 - image: set-labels:v0.1.5 87 exclude: 88 - kind: Deployment 89 ``` 90 91 #### Example: Exclude all resources that have both group "apps" and kind "Deployment" 92 93 ```shell 94 $ kpt fn eval [PKG_DIR] -i set-labels:v0.1.5 --exclude-kind Deployment --exclude-group apps 95 ``` 96 ```yaml 97 # pipeline of Kptfile 98 pipeline: 99 mutators: 100 - image: set-labels:v0.1.5 101 exclude: 102 - kind: Deployment 103 group: apps 104 ``` 105 106 #### Example: Exclude all resources that have either group "apps" or kind "Deployment" 107 108 ```yaml 109 # pipeline of Kptfile 110 pipeline: 111 mutators: 112 - image: set-labels:v0.1.5 113 exclude: 114 - kind: Deployment 115 - group: apps 116 ``` 117 118 With the current proposal, this is not possible imperatively with kpt fn eval. 119 120 #### Example: Select all resources that have group "apps", but do NOT have kind "Deployment" 121 122 ```shell 123 $ kpt fn eval [PKG_DIR] -i set-labels:v0.1.5 --match-group apps --exclude-kind Deployment 124 ``` 125 ```yaml 126 # pipeline of Kptfile 127 pipeline: 128 mutators: 129 - image: set-labels:v0.1.5 130 selectors: 131 group: apps 132 exclude: 133 - kind: Deployment 134 ``` 135 136 ### Selecting by labels or annotations 137 138 We will support selection and exclusion with annotation and label selectors. 139 140 ```shell 141 $ kpt fn eval [PKG_DIR] -i set-labels:v0.1.5 --match-annotation foo=bar --exclude-annotation config.kubernetes.io/local-config=true 142 ``` 143 144 ```yaml 145 # pipeline of Kptfile 146 pipeline: 147 mutators: 148 - image: set-labels:v0.1.5 149 selectors: 150 - annotations: 151 foo: bar 152 exclude: 153 - annotations: 154 config.kubernetes.io/local-config: "true" 155 ``` 156 157 ## Open Issues/Questions 158 159 ### How should kpt functions handle meta resources? 160 161 One concern about this approach is that in order to exclude the Kptfile from being modified by horizontal 162 transformations like set-namespace and set-labels, the user will have to write an exclusion field for each function. 163 Arguably, the user shouldn't have to provide any special syntax for the Kptfile at all, because kpt and 164 kpt functions should be able to handle it correctly. A mitigation for this is that our own horizontal kpt functions 165 can exclude the Kptfile within the function logic itself, and there will be no special handling logic in kpt. 166 167 ## Alternatives Considered 168 169 ### A new annotation to decide if a kpt function should modify it 170 171 We can introduce a new annotation that determines if functions should modify it. 172 173 ```yaml 174 apiVersion: kpt.dev/v1 175 kind: Kptfile 176 metadata: 177 name: example 178 annotations: 179 config.kubernetes.io/hydration-override: false 180 ``` 181 182 If kpt sees `config.kubernetes.io/hydration-override: false`, it won't allow the functions to modify the resource. The user can add 183 this annotation to every resource that they don't want functions to modify. 184 185 Pros: 186 - The user would not need to write an exclusion field for each function. 187 188 Cons: 189 - It will not be possible to control at a function level. If users want some functions to modify the Kptfile/meta resources, and others not to touch it, 190 they will have to re-organize their package. 191 192 193 ### Use the existing selector mechanism 194 195 We can recommend that users use the existing selectors to exclude the Kptfile and functionConfigs if they don't want functions to run on them. 196 Here is an example: https://github.com/natasha41575/kpt-exclude-kptfile/blob/main/Kptfile. The Kptfile looks like: 197 198 ```yaml 199 apiVersion: kpt.dev/v1 200 kind: Kptfile 201 metadata: 202 name: example 203 pipeline: 204 mutators: 205 - image: gcr.io/kpt-fn/set-labels:unstable 206 configPath: functionconfig.yaml 207 selectors: 208 - apiVersion: "batch/v1" 209 - apiVersion: "apps/v1" 210 - apiVersion: "v1" 211 - apiVersion: "example.com/v1" 212 ``` 213 214 Some problems with this approach: 215 - It is verbose. 216 - Verbosity increases if the user has more resources in the package. 217 - The user will have to keep track of an exhaustive list of all their resources in their package just to exclude the Kptfile. 218 - kpt and kpt functions should already know about the Kptfile, so this overhead on the user's side is unnecessary. 219 220 ### Rely on the existing annotation config.kubernetes.io/local-config 221 222 We can exclude all local-config resources (i.e. resources with the annotation `config.kubernetes.io/local-config: true`) from functions. This annotation is 223 currently used by kpt live apply to determine whether to apply the resource to the cluster. However, users may have some resources that they want kpt to modify or be 224 available as function inputs, but that they don't want to be applied to the cluster. In these cases, overloading the annotation in this way will 225 break some functions. 226 227 ### Mark meta resources with an annotation 228 Kpt can add the annotation config.kubernetes.io/meta-resource: true to all meta resources, to allow users to easily target the Kptfile and functionConfigs. 229 Users can then use the annotation selector mechanism to target meta resources if desired. 230 231 However, because most meta resources already have the `config.kubernetes.io/local-config: true` annotation, a new meta resource annotation is not necessary. 232 With the proposed `exclude` mechanism, users can filter out local-config easily, and in other cases, Kind- based exclusion is good enough. 233