github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/site/book/05-developing-functions/02-developing-in-Go.md (about) 1 You can develop a KRM function in Go using [the kpt function SDK]. 2 3 - **General-purpose language:** Compared to Domain Specific Languages (DSL), Go 4 is a general-purpose programming language that provides: 5 - Proper abstractions and language features 6 - An extensive ecosystem of tooling (e.g. IDE support) 7 - A comprehensive catalog of well-supported libraries 8 - Robust community support and detailed documentation 9 10 ## Prerequisites 11 12 - [Install kpt](https://kpt.dev/installation/) 13 14 - [Install Docker](https://docs.docker.com/get-docker/) 15 16 ## Quickstart 17 18 In this quickstart, we will write a function that adds an annotation 19 `config.kubernetes.io/managed-by=kpt` to all `Deployment` resources. 20 21 ### Initialize your project 22 23 We start from a "get-started" package which contains a `main.go` file with some scaffolding code. 24 25 ```shell 26 # Set your KRM function name. 27 export FUNCTION_NAME=set-annotation 28 29 # Get the "get-started" package. 30 kpt pkg get https://github.com/GoogleContainerTools/kpt-functions-sdk.git/go/get-started@master ${FUNCTION_NAME} 31 32 cd ${FUNCTION_NAME} 33 34 # Initialize the Go module 35 go mod init 36 go mod tidy 37 ``` 38 39 ### Write the KRM function logic 40 41 Take a look at the `main.go` (as below) and complete the `Run` function. 42 43 ```go 44 // main.go 45 package main 46 47 import ( 48 "fmt" 49 "os" 50 51 "github.com/GoogleContainerTools/kpt-functions-sdk/go/fn" 52 ) 53 54 // EDIT THIS FUNCTION! 55 // This is the main logic. rl is the input `ResourceList` which has the `FunctionConfig` and `Items` fields. 56 // You can modify the `Items` and add result information to `rl.Results`. 57 func Run(rl *fn.ResourceList) (bool, error) { 58 // Your code 59 } 60 61 func main() { 62 // CUSTOMIZE IF NEEDED 63 // `AsMain` accepts a `ResourceListProcessor` interface. 64 // You can explore other `ResourceListProcessor` structs in the SDK or define your own. 65 if err := fn.AsMain(fn.ResourceListProcessorFunc(Run)); err != nil { 66 os.Exit(1) 67 } 68 } 69 ``` 70 71 The [`fn`] library provides a series of KRM level operations for [`ResourceList`]. 72 Basically, the KRM resource `ResourceList.FunctionConfig` and KRM resources `ResourceList.Items` are both converted to 73 `KubeObject` objects. You can use `KubeObject` similar as [`unstructured.Unstrucutred`]. 74 75 The set-annotation function (see below) iterates the `ResourceList.Items`, finds out the `Deployment` resources and 76 adds the annotation. After the iteration, it adds some user message to the `ResourceList.Results` 77 78 ```go 79 func Run(rl *fn.ResourceList) (bool, error) { 80 for _, kubeObject := range rl.Items { 81 if kubeObject.IsGVK("apps/v1", "Deployment") { 82 kubeObject.SetAnnotation("config.kubernetes.io/managed-by", "kpt") 83 } 84 } 85 // This result message will be displayed in the function evaluation time. 86 rl.Results = append(rl.Results, fn.GeneralResult("Add config.kubernetes.io/managed-by=kpt to all `Deployment` resources", fn.Info)) 87 return true, nil 88 } 89 ``` 90 91 Learn more about the `KubeObject` from the [go doc](https://pkg.go.dev/github.com/GoogleContainerTools/kpt-functions-sdk/go/fn). 92 93 94 ### Test the KRM function 95 96 The "get-started" package contains a `./data` directory. You can use this to test out your functions. 97 98 ```shell 99 # Edit the `data/resources.yaml` with your KRM resources. 100 # resources.yaml already has a `Deployment` and `Service` as test data. 101 vim data/resources.yaml 102 103 # Convert the KRM resources and FunctionConfig resource to `ResourceList`, and 104 # then pipe the ResourceList as StdIn to your function 105 kpt fn source data | go run main.go 106 107 # Verify the KRM function behavior in the StdOutput `ResourceList` 108 ``` 109 110 ### Build the KRM function as a Docker image 111 112 Build the image 113 114 The "get-started" package provides the `Dockerfile`. 115 116 ```shell 117 export FN_CONTAINER_REGISTRY=<Your GCR or docker hub> 118 export TAG=<Your KRM function tag> 119 docker build . -t ${FN_CONTAINER_REGISTRY}/${FUNCTION_NAME}:${TAG} 120 ``` 121 122 To verify the image using the same `./data` resources 123 ```shell 124 kpt fn eval ./data --image ${FN_CONTAINER_REGISTRY}/${FUNCTION_NAME}:${TAG} 125 ``` 126 127 ## Next Steps 128 129 - See other [go doc examples] to use KubeObject. 130 - To contribute to KRM catalog functions, please follow the [contributor guide](https://github.com/GoogleContainerTools/kpt-functions-catalog/blob/master/CONTRIBUTING.md) 131 132 [the kpt function SDK]: https://pkg.go.dev/github.com/GoogleContainerTools/kpt-functions-sdk/go/fn 133 [go doc examples]: https://pkg.go.dev/github.com/GoogleContainerTools/kpt-functions-sdk/go/fn/examples 134 [`fn`]: https://pkg.go.dev/github.com/GoogleContainerTools/kpt-functions-sdk/go/fn 135 [`ResourceList`]: https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md 136 [`unstructured.Unstructured`]: https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured