github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/site/book/05-developing-functions/03-developing-in-Typescript.md (about) 1 kpt project provides an opinionated Typescript SDK for implementing functions. 2 It provides the following features: 3 4 - **General-purpose language:** Similar to Go, Typescript is a general-purpose 5 programming language that provides: 6 - Proper abstractions and language features 7 - An extensive ecosystem of tooling (e.g. IDE support) 8 - A comprehensive catalog of well-supported libraries 9 - Robust community support and detailed documentation 10 - **Idiomatic:** The TS SDK provides a different level of abstraction compared 11 to the Go library we saw previously. Instead of exposing the low-level YAML 12 AST, resources are marshalled into native Typescript objects. As a result, you 13 get a more idiomatic and high-level abstraction. Ideally, you should work with 14 native data structure/object in each language and not think about YAML which 15 is just a file format. Even though resources in configuration files are 16 round-tripped to Typescript objects, the kpt orchestrator ensures that 17 YAML-specific constructs such as comments are preserved. The obvious 18 limitation of this high-level abstraction is that you cannot develop functions 19 for manipulating YAML-specific constructs like comments. 20 - **Type-safety:** Kubernetes configuration is typed, and its schema is defined 21 using the OpenAPI spec. Typescript has a sophisticated type system that 22 accommodates the complexity of Kubernetes resources. The TS SDK enables 23 generating Typescript classes for core and CRD types. 24 - **Batteries-included:** The TS SDK provides a simple, powerful API for 25 querying and manipulating resources inspired by [document-oriented databases]. 26 It provides the scaffolding required to develop, build, test, and publish 27 functions, allowing you to focus on implementing your business-logic. 28 29 ## Quickstart 30 31 This quickstart will get you started developing a kpt function with the TS SDK. 32 33 ### System Requirements 34 35 Currently supported platforms: amd64 Linux/Mac 36 37 - Install [kpt][download-kpt] and its dependencies 38 - Install [node][download-node] 39 - The SDK requires `npm` version 6 or higher. 40 - If installing node from binaries (i.e. without a package manager), follow 41 these [installation instructions][install-node]. 42 43 ### Explore the Demo Functions Package 44 45 1. Get the `demo-functions` package: 46 47 ```shell 48 $ git clone --depth 1 https://github.com/GoogleContainerTools/kpt-functions-sdk.git 49 ``` 50 51 All subsequent commands are run from the `demo-functions` directory: 52 53 ```shell 54 $ cd kpt-functions-sdk/ts/demo-functions 55 ``` 56 57 1. Install all dependencies: 58 59 ```shell 60 $ npm install 61 ``` 62 63 1. Run the following in a separate terminal to continuously build your function 64 as you make changes: 65 66 ```shell 67 $ npm run watch 68 ``` 69 70 1. Explore the [`label_namespace`][label-namespace] transformer function. This 71 function takes a given `label_name` and `label_value` to add the appropriate 72 label to `Namespace` objects using the SDK's `addLabel` function. 73 74 ```typescript 75 import { addLabel, Configs } from "kpt-functions"; 76 import { isNamespace } from "./gen/io.k8s.api.core.v1"; 77 78 export const LABEL_NAME = "label_name"; 79 export const LABEL_VALUE = "label_value"; 80 81 export async function labelNamespace(configs: Configs) { 82 const labelName = configs.getFunctionConfigValueOrThrow(LABEL_NAME); 83 const labelValue = configs.getFunctionConfigValueOrThrow(LABEL_VALUE); 84 configs 85 .get(isNamespace) 86 .forEach((n) => addLabel(n, labelName, labelValue)); 87 } 88 ``` 89 90 1. Run the `label_namespace` function on the `example-configs` directory: 91 92 ```shell 93 $ export CONFIGS=../../example-configs 94 ``` 95 96 ```shell 97 $ kpt fn eval $CONFIGS --exec "node dist/label_namespace_run.js" -- label_name=color label_value=orange 98 ``` 99 100 As the name suggests, this function added the given label to all `Namespace` 101 objects in the `example-configs` directory: 102 103 ```shell 104 $ git diff $CONFIGS 105 ``` 106 107 1. Try modifying the function in `src/label_namespace.ts` to perform other 108 operations and rerun the function on `example-configs` to see the changes. 109 110 1. Explore validation functions like [validate-rolebinding]. Instead of 111 transforming configuration, this function searches RoleBindings and returns a 112 results field containing details about invalid subject names. 113 114 ```typescript 115 import { Configs, kubernetesObjectResult } from "kpt-functions"; 116 import { isRoleBinding } from "./gen/io.k8s.api.rbac.v1"; 117 118 const SUBJECT_NAME = "subject_name"; 119 120 export async function validateRolebinding(configs: Configs) { 121 // Get the subject name parameter. 122 const subjectName = configs.getFunctionConfigValueOrThrow(SUBJECT_NAME); 123 124 // Iterate over all RoleBinding objects in the input 125 // Filter those that have a subject we're looking for. 126 const results = configs 127 .get(isRoleBinding) 128 .filter( 129 (rb) => 130 rb && rb.subjects && rb.subjects.find((s) => s.name === subjectName) 131 ) 132 .map((rb) => 133 kubernetesObjectResult(`Found banned subject '${subjectName}'`, rb) 134 ); 135 136 configs.addResults(...results); 137 } 138 ``` 139 140 1. Run `validate-rolebinding` on `example-configs`. 141 142 ```shell 143 $ kpt fn eval $CONFIGS --exec "node dist/validate_rolebinding_run.js" -- subject_name=alice@foo-corp.com 144 ``` 145 146 Look at the changes made by the function: 147 148 ```shell 149 $ git diff $CONFIGS 150 ``` 151 152 1. Explore generator functions like [expand-team-cr]. This function generates a 153 per-environment Namespace and RoleBinding object for each custom resource 154 (CR) of type Team. 155 156 ```typescript 157 import { Configs } from "kpt-functions"; 158 import { isTeam, Team } from "./gen/dev.cft.anthos.v1alpha1"; 159 import { Namespace } from "./gen/io.k8s.api.core.v1"; 160 import { RoleBinding, Subject } from "./gen/io.k8s.api.rbac.v1"; 161 162 const ENVIRONMENTS = ["dev", "prod"]; 163 164 export async function expandTeamCr(configs: Configs) { 165 // For each 'Team' custom resource in the input: 166 // 1. Generate a per-enviroment Namespace. 167 // 2. Generate RoleBindings in each Namespace. 168 configs.get(isTeam).forEach((team) => { 169 const name = team.metadata.name; 170 171 ENVIRONMENTS.forEach((suffix) => { 172 const ns = `${name}-${suffix}`; 173 configs.insert(Namespace.named(ns)); 174 configs.insert(...createRoleBindings(team, ns)); 175 }); 176 }); 177 } 178 179 function createRoleBindings(team: Team, namespace: string): RoleBinding[] { 180 return (team.spec.roles || []).map((item) => { 181 return new RoleBinding({ 182 metadata: { 183 name: item.role, 184 namespace, 185 }, 186 subjects: roleSubjects(item), 187 roleRef: { 188 kind: "ClusterRole", 189 name: item.role, 190 apiGroup: "rbac.authorization.k8s.io", 191 }, 192 }); 193 }); 194 } 195 196 function roleSubjects(item: Team.Spec.Item): Subject[] { 197 const userSubjects: Subject[] = (item.users || []).map( 198 (user) => 199 new Subject({ 200 kind: "User", 201 name: user, 202 }) 203 ); 204 const groupSubjects: Subject[] = (item.groups || []).map( 205 (group) => 206 new Subject({ 207 kind: "Group", 208 name: group, 209 }) 210 ); 211 return userSubjects.concat(groupSubjects); 212 } 213 ``` 214 215 1. Run `expand-team-cr` on `example-configs`. 216 217 ```shell 218 $ kpt fn eval $CONFIGS --exec "node dist/expand_team_cr_run.js" 219 ``` 220 221 Look at the changes made by the function: 222 223 ```shell 224 $ git diff $CONFIGS 225 ``` 226 227 ## Next Steps 228 229 - Read the complete [Typescript SDK Developer Guide]. 230 - Take a look at these [example functions] to better understand how to use the 231 TS SDK. 232 233 [download-kpt]: /book/01-getting-started/01-system-requirements 234 [download-node]: https://nodejs.org/en/download/ 235 [install-node]: https://github.com/nodejs/help/wiki/Installation/ 236 [ts sdk api]: https://googlecontainertools.github.io/kpt-functions-sdk/api/ 237 [label-namespace]: 238 https://github.com/GoogleContainerTools/kpt-functions-sdk/blob/master/ts/demo-functions/src/label_namespace.ts 239 [validate-rolebinding]: 240 https://github.com/GoogleContainerTools/kpt-functions-sdk/blob/master/ts/demo-functions/src/validate_rolebinding.ts 241 [expand-team-cr]: 242 https://github.com/GoogleContainerTools/kpt-functions-sdk/blob/master/ts/demo-functions/src/expand_team_cr.ts 243 [example functions]: 244 https://github.com/GoogleContainerTools/kpt-functions-sdk/tree/master/ts/demo-functions/src/ 245 [document-oriented databases]: 246 https://en.wikipedia.org/wiki/Document-oriented_database 247 [typescript sdk developer guide]: /sdk/ts-guide