fn-framework-application

module
v0.0.0-...-e244b83 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 6, 2024 License: Apache-2.0

README

Kyaml Functions Framework Example: Application Custom Resource

This is a moderate-complexity example of a KRM function built using the KRM Functions Framework package. It demonstrates how to write a function that implements a custom resource (CR) representing an abstract application.

apiVersion: platform.example.com/v1alpha1
kind: ExampleApp
metadata:
  name: simple-app-sample
env: production
workloads:
  webWorkers:
    - name: web-worker
      domains:
      - example.com
  jobWorkers:
    - name: job-worker
      replicas: 10
      resources: medium
      queues:
      - high
      - medium
      - low
    - name: job-worker-2
      replicas: 5
      queues:
      - bg2
datastores:
  postgresInstance: simple-app-sample-postgres

It also demonstrates the pattern of having the CR accept patches, allowing the user to customize the final result beyond the fields the CR exposes.

apiVersion: platform.example.com/v1alpha1
kind: ExampleApp
metadata:
  name: simple-app-sample
env: production
workloads:
  webWorkers:
    - name: web-worker
      domains:
      - first.example.com
    - name: web-worker-no-sidecar
      domains:
      - second.example.com

overrides:
  additionalResources:
    - custom-configmap.yaml
  resourcePatches:
    - web-worker-sidecar.yaml
  containerPatches:
    - custom-app-env.yaml

Implementation walkthrough

The entrypoint for the function is cmd/main.go, which invokes a "dispatcher" that determines which Filter implements the resource passed in. The dispatcher pattern allows a single function binary to handle multiple CRs, and is also useful for evolving a single CR over time (e.g. handle ExampleApp API versions example.com/v1beta1 and example.com/v1).

	p := framework.VersionedAPIProcessor{FilterProvider: framework.GVKFilterMap{
		"ExampleApp": map[string]kio.Filter{
			"platform.example.com/v1alpha1": &v1alpha1.ExampleApp{},
		},
	}}

The ExampleApp type is defined in pkg/exampleapp/v1alpha1/types.go. It is responsible for implementing the logic of the CR, most of which is done by implementing the kyaml.Filter interface in pkg/exampleapp/v1alpha1/processing.go. Internally, the filter function mostly builds up and executes a framework.TemplateProcessor.

The ExampleApp type is annotated with kubebuilder markers, and a Go generator uses those to create the CRD YAML in pkg/exampleapp/v1alpha1/platform.example.com_exampleapps.yaml. The CR then implements framework.ValidationSchemaProvider, which causes the CRD to be used for validation. It also implements framework.Validator to add custom validations and framework.Defaulter to add defaulting.

type ExampleApp struct {
	// Embedding these structs is required to use controller-gen to produce the CRD
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`

	// +kubebuilder:validation:Enum=production;staging;development
	Env string `json:"env" yaml:"env"`

	// +optional
	AppImage string `json:"appImage" yaml:"appImage"`

	Workloads Workloads `json:"workloads" yaml:"workloads"`

	// +optional
	Datastores Datastores `json:"datastores,omitempty" yaml:"datastores,omitempty"`

	// +optional
	Overrides Overrides `json:"overrides,omitempty" yaml:"overrides,omitempty"`
}
func (a ExampleApp) Filter(items []*yaml.RNode) ([]*yaml.RNode, error) {
func (a *ExampleApp) Schema() (*spec.Schema, error) {
func (a *ExampleApp) Validate() error {
func (a *ExampleApp) Default() error {

Running the Example

There are three ways to try this out:

A. Run make example in the root of the example to run the function with the test data in pkg/exampleapp/v1alpha1/testdata/success/basic.

B. Run go run cmd/main.go [FILE] in the root of the example. Try it with the test input from one of the cases in pkg/exampleapp/v1alpha1/testdata/success. For example: go run cmd/main.go pkg/exampleapp/v1alpha1/testdata/success/basic/config.yaml.

C. Build the binary with make build, then run it with app-fn [FILE]. Try it with the test input from one of the cases in pkg/exampleapp/v1alpha1/testdata/success. For example: app-fn pkg/exampleapp/v1alpha1/testdata/success/basic/config.yaml.

Directories

Path Synopsis
pkg

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL