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