-
Notifications
You must be signed in to change notification settings - Fork 237
[WIP] Function SDK guide #3367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[WIP] Function SDK guide #3367
Conversation
mkdir -p $GOPATH/src/${FUNCTION_PATH} && cd $GOPATH/src/${FUNCTION_PATH} | ||
|
||
# Get the "get-started" package. | ||
kpt pkg get https://github.com/GoogleContainerTools/kpt-functions-sdk.git/go/get-started-runner@master ${FUNCTION_NAME} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line didn't work for me ...
Error: path "/go/get-started-runner" does not exist in repo "https://github.com/GoogleContainerTools/kpt-functions-sdk"
Do I need to merge a PR in kpt-functions-sdk?
} | ||
} | ||
``` | ||
`FunctionX` implements the [`Runner`] interface that can process the input KRM resources as [`fn.ResourceList`], it initializes `fn.KubeObject` to hold the KRM resources, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to mention ResourceList?
} | ||
``` | ||
`FunctionX` implements the [`Runner`] interface that can process the input KRM resources as [`fn.ResourceList`], it initializes `fn.KubeObject` to hold the KRM resources, | ||
so that you can use [`fn.KubeObject` and `fn.SubObject`] methods directly. After `Run`, it will convert the modified `fn.KubeObjects` to KRM resources. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of "it initializes fn.KubeObject
to hold the KRM resources, so that you can use [fn.KubeObject
and fn.SubObject
] methods directly", I would just say that something like "the objects passed to the function are available in items. These objects can be modified in place and are used as the output of the function".
`FunctionX` implements the [`Runner`] interface that can process the input KRM resources as [`fn.ResourceList`], it initializes `fn.KubeObject` to hold the KRM resources, | ||
so that you can use [`fn.KubeObject` and `fn.SubObject`] methods directly. After `Run`, it will convert the modified `fn.KubeObjects` to KRM resources. | ||
|
||
### Define configures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe Define function parameters
or Define function arguments
?
Otherwise you can skip this step and move to next. | ||
```go | ||
type FunctionX struct { | ||
FnConfigBool bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe SomeBoolValue
, SomeIntValue
, SomeStringValue
instead of the FnConfig
prefix - otherwise the question is whether the FnConfig
prefix matters
## Write the main logic in `Run` | ||
|
||
The SDK will initialize a slice of `*fn.KubeObject` to hold your KRM resources. You will need to pass the | ||
KRM resources from the input in `items` fields. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we've said this already?
// clusterScoped contains only cluster scoped resources | ||
clusterScoped := objects.Where(func(o *fn.KubeObject) bool { return o.IsClusterScoped() }) | ||
// customDeployment contains all resources of Kind "CustomDeployment", in Group "fn.kpt.dev" with any Versions. | ||
customDeployment := objects.Where(fn.IsGVK("fn.kpt.dev", "", "CustomDeployment") }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I would support IsGK instead of IsGVK with a magic empty value
The `fn.KubeObjects` is a slice of `*fn.KubeObject`, that you can apply some select logic to easily choose | ||
the target KRM resources. See below example on using `Where` and `WhereNot` to filter different types of resources. | ||
```go | ||
func (r *YourFunction) Run(context *fn.Context, functionConfig *fn.KubeObject, items fn.KubeObjects) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: if these are just examples, don't wrap them in a Run function ... otherwise users will think we're actually doing something here....
```go | ||
func (r *YourFunction) Run(context *fn.Context, functionConfig *fn.KubeObject, items fn.KubeObjects) { | ||
// Get first deployment object. | ||
deployment := items.Where(fn.IsGVK("apps", "v1", "Deployment")).Where(func(o *fn.KubeObject) bool{return o.GetName() == "nginx"})[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably want HasName or IsName, but OTOH it is helpful to spell this out.
You could spell it out, and then say "you can also use the IsName helper method, which produces the same filter function"
### Copy `KubeObject` to a typed struct | ||
|
||
If you already have some struct to define a KRM resource (like `corev1.ConfigMap`), you can switch the `KubeObject` | ||
to the other type via `As` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add an explicit warning that this copies the object and thus you have to copy it back
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for writing this. I have a few minor comments.
@@ -18,6 +18,8 @@ You can develop a KRM function in Go using [the kpt function SDK]. | |||
In this quickstart, we will write a function that adds an annotation | |||
`config.kubernetes.io/managed-by=kpt` to all `Deployment` resources. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: config.kubernetes.io/managed-by:kpt
( s/=/:)
This guide gives tips to effectively write a KRM function. | ||
|
||
This guide is for advanced kpt function users who find the [catalog.kpt.dev] cannot fulfil their needs | ||
and want to design their own KRM functions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think advanced kpt users
can confuse users and might discourage users to read further.
Maybe we can combine this line and previous line with something along the lines of ...
This guide describes best practices and patterns on how to structure your Go KRM functions.
This guide is for advanced kpt function users who find the [catalog.kpt.dev] cannot fulfil their needs | ||
and want to design their own KRM functions. | ||
|
||
Suggest reading [Developing in Go] first |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit .
missing at the end.
## Prerequisites | ||
|
||
- [Install kpt] | ||
- [Install Docker] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will be good to specify minimum version of Go. I think Go 1.17+
is what we have been using for the toolset.
mkdir -p $GOPATH/src/${FUNCTION_PATH} && cd $GOPATH/src/${FUNCTION_PATH} | ||
|
||
# Get the "get-started" package. | ||
kpt pkg get https://github.com/GoogleContainerTools/kpt-functions-sdk.git/go/get-started-runner@master ${FUNCTION_NAME} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assuming myself as a Go developer, I will find this step to be awkward :) and I will also be surprised to see files such as Kptfile
etc. It might get confusing. Can we just use git clone
or something to fetch the skeleton code ?
```go | ||
func (r *YourFunction) Run(context *fn.Context, functionConfig *fn.KubeObject, items fn.KubeObjects) { | ||
// Get first deployment object. | ||
deployment := items.Where(fn.IsGVK("apps", "v1", "Deployment")).Where(func(o *fn.KubeObject) bool{return o.GetName() == "nginx"})[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's okay to have this expression in multiple lines that helps with readability.
@@ -107,5 +107,6 @@ | |||
- [Namespace Provisioning UI](guides/namespace-provisioning-ui.md) | |||
- [Variant Constructor Pattern](guides/variant-constructor-pattern.md) | |||
- [Value Propagation Pattern](guides/value-propagation.md) | |||
- [Effective Go KRM functions](guides/effective-go-krm-function.md) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it makes sense to have it alongside Getting Started
instead of guides
?
This guide focuses on explaining the KRM resource editing patterns.