github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/site/book/07-effective-customizations/01-single-value-replacement.md (about) 1 ## Scenario 2 3 I have a single value replacement in my package. I don’t want package consumers 4 to look through all the yaml files to find the value I want them to set. It 5 seems easier to just create a parameter for this value and have the user look 6 at Kptfile for inputs. 7 8 Example storage bucket: 9 10 ```yaml 11 apiVersion: storage.cnrm.cloud.google.com/v1beta1 12 kind: StorageBucket 13 metadata: 14 name: my-bucket # kpt-set: ${project-id}-${name} 15 namespace: ns-test # kpt-set: ${namespace} 16 annotations: 17 cnrm.cloud.google.com/force-destroy: "false" 18 cnrm.cloud.google.com/project-id: my-project # kpt-set: ${project-id} 19 spec: 20 storageClass: standard # kpt-set: ${storage-class} 21 uniformBucketLevelAccess: true 22 versioning: 23 enabled: false 24 ``` 25 26 The corresponding Kptfile: 27 28 ```yaml 29 apiVersion: kpt.dev/v1 30 kind: Kptfile 31 metadata: 32 name: bucket 33 info: 34 description: A Google Cloud Storage bucket 35 pipeline: 36 mutators: 37 - image: gcr.io/kpt-fn/apply-setters:v0.2 38 configMap: 39 name: todo-bucket-name 40 namespace: todo-namespace 41 project-id: todo-project-id 42 storage-class: standard 43 ``` 44 45 46 ## Problems 47 48 1. With package popularity the single values inevitably expand to provide a 49 facade to a large portion of the data. That defeats the purpose of minimizing 50 the cognitive load. With this small example almost half of the StorageBucket configuration is now covered with parameters. 51 1. Some values like resource names are used as references so setting them in 52 one place needs to trigger updates in all the places where they are referenced. 53 1. If additional resources that have similar values are added to the package 54 new string replacements need to be added. In this case everything will need 55 to also be marked up with project ID and namespace. 56 1. If a package is used as a sub-package the string replacement parameters need 57 to be surfaced to the parent package and if the parent package already expects 58 some values to be set and the parameters do not exist, the sub-package needs to 59 be updated. 60 61 ## Solutions: 62 63 1. kpt allows the user to edit a particular value directly in the configuration 64 data and will handle upstream merge. When [editing the yaml] directly the 65 consumers are not confined to the parameters that the package author has 66 provided. [kpt pkg update] merges the local edits made by consumer with the 67 changes in the upstream package made by publisher. In this case `storageClass` 68 can be set directly by the user. 69 1. Attributes like resource names which are often updated by consumers to add 70 prefix or suffix (e.g. *-dev, *-stage, *-prod, na1-*, eu1-*) are best handled 71 by the [ensure-name-substring] function that will handle dependency updates as 72 well as capture all the resources in the package. 73 1. Instead of setting a particular value on a resource a bulk operation can be 74 applied to all the resources that fit a particular interface. This can be done 75 by a custom function or by [set-namespace], [search-and-replace] , [set-labels] 76 and [set-annotations] functions. 77 78 New bucket configuration: 79 80 ```yaml 81 apiVersion: storage.cnrm.cloud.google.com/v1beta1 82 kind: StorageBucket 83 metadata: 84 name: bucket 85 annotations: 86 cnrm.cloud.google.com/force-destroy: "false" 87 spec: 88 storageClass: standard 89 uniformBucketLevelAccess: true 90 versioning: 91 enabled: false 92 ``` 93 94 The suggested customizations are now in the Kptfile: 95 96 ```yaml 97 apiVersion: kpt.dev/v1 98 kind: Kptfile 99 metadata: 100 name: bucket 101 info: 102 description: A Google Cloud Storage bucket 103 pipeline: 104 mutators: 105 - image: gcr.io/kpt-fn/set-namespace:v0.2.0 106 configMap: 107 namespace: example-ns 108 - image: gcr.io/kpt-fn/ensure-name-substring:v0.1.1 109 configMap: 110 prepend: project111- 111 - image: gcr.io/kpt-fn/set-annotations:v0.1.4 112 configMap: 113 cnrm.cloud.google.com/project-id: project111 114 ``` 115 116 The resource configuration YAML doesn't need to be marked up with where the 117 namespace value needs to go. The [set-namespace] function is smart enough to 118 find all the appropriate resources that need the namespace. 119 120 We have put in the starter name `bucket` and have an [ensure-name-substring] 121 that shows the package consumer that the project ID prefix is what we suggest. 122 However if they have a different naming convention they can alter the name 123 prefix or suffix on all the resources in the pacakge. 124 125 Since we are trying to set the annotation to the project ID we can use the 126 [set-annotations] function one time and the annotation are going to be set on 127 all the resources in the package. If we add additional resources or whole 128 sub packages we will get the consistent annotations across all resources 129 without having to find all the places where annotations can go. 130 131 [editing the yaml]: /book/03-packages/03-editing-a-package 132 [kpt pkg update]: /book/03-packages/05-updating-a-package 133 [ensure-name-substring]: https://catalog.kpt.dev/ensure-name-substring/v0.1/ 134 [search-and-replace]: https://catalog.kpt.dev/search-replace/v0.2/ 135 [set-labels]: https://catalog.kpt.dev/set-labels/v0.1/ 136 [set-annotations]: https://catalog.kpt.dev/set-annotations/v0.1/ 137 [set-namespace]: https://catalog.kpt.dev/set-namespace/v0.2/