Skip to content

Latest commit

 

History

History
206 lines (167 loc) · 7.34 KB

creating-gatewayclass-definitions.md

File metadata and controls

206 lines (167 loc) · 7.34 KB

Creating GatewayClass Definitions

This document describes how to create new GatewayClass definitions. See also Example GatewayClass Definitions for the definitions provided with the bifrost-gateway-controller.

Before preparing new GatewayClass definitions, it is important to understand the normalization implemented by the controller, since GatewayClass definitions typically will use the normalized specifications to define actual data path resources. See Normalization of Gateway Resources.

GatewayClass and GatewayClassBlueprint Resources

The actual implementation of data-paths are defined by GatewayClassBlueprint resources and the purpose of GatewayClass resources is to name a given class, reference a GatewayClassBlueprint resource and map the class to a specific controller. See also Gateway API on GatewayClass documentation

The GatewayClassBlueprint is a specific extension of this controller.

A GatewayClass resource may look like the following. Note how we specify our own controller name and a default-gateway-class resource of kind GatewayClassBlueprint for parameters associated with the GatewayClass:

apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
  name: example
spec:
  controllerName: "github.com/tv2-oss/bifrost-gateway-controller"
  parametersRef:
    group: v1alpha1
    kind: GatewayClassBlueprint
    name: default-gateway-class

A GatewayClassBlueprint contains templates for the sub-resource(s) that implement the data-path. There are template(s) related to both Gateway and HTTPRoute resources, and the general format is shown below (with template details left out):

apiVersion: gateway.tv2.dk/v1alpha1
kind: GatewayClassBlueprint
metadata:
  name: default-gateway-class
spec:

  # The following are templates used to 'implement' a 'parent' Gateway
  gatewayTemplate:
    resourceTemplates:
      # ... actual templates go here

  # The following are templates used to 'implement' a 'parent' HTTPRoute
  httpRouteTemplate:
    resourceTemplates:
      # ... actual templates go here

Gateway and HTTPRoute resources are handled independently. I.e. when a Gateway resource is defined using a GatewayClass for our controller, 'shadow' resources will be created using the template(s) defined under gatewayTemplate.resourceTemplates in the GatewayClassBlueprint associated with the given GatewayClass. Similarly, 'shadow' resources will be created for HTTPRoute resources using the templates under httpRouteTemplate.resourceTemplates

Templates are Golang YAML templates (similar to e.g. Helm), and includes support for the 100+ functions from the Sprig library as well as a toYaml function.

Typically templates will result in a single resource, but conditionals and loops may result in templates rendering to zero or more than one resource. This is supported but should be used with caution.

Consideration for multi-resource templates:

  • Resources should be separated by a line with --- (like in Helm).

  • The template as a whole is a single unit in the graph of resources, i.e. individual resources in a template cannot refer to each other using the .Resources method described below. References across templates using multiple resources are supported.

  • It is supported to mix resource kinds in a single template, however, consider if it would be more appropriate to use separate templates in such cases.

Namespaced Resources

Namespace-scoped templated resources are always created in the namespace of the parent resource, e.g. a resource defined under gatewayTemplate will be created in the namespace of the parent Gateway resource.

Inter-resource References

Resources may reference other resources, e.g. a status field from one resource can be used in the template of another resource. When resources have been created in the API server, they will be available for templating of other resources. However, the dependencies must be a directed acyclic graph.

When a resource template can be rendered without missing references, the rendered template will be used to retrieve the current version of the resource from the API server. These 'current resources' will be made available as template variables under .Resources and the name of the template. Since a template may render to more than one resource, the .Resources variable is a list.

The following excerpt from a GatewayClassBlueprint illustrates how a value is read from the status field of one resource LBTargetGroup and how the status.atProvider.arn value is used in the template of TargetGroupBinding through .Resources.LBTargetGroup. The use of the index function is because we refer to the first resource rendered from the LBTargetGroup template. This is necessary even if we in this case know that there is always only a single resource rendered from the template.

...
spec:
  gatewayTemplate:
    resourceTemplates:
      LBTargetGroup: |
        kind: LBTargetGroup
        metadata:
          name: gw-{{ .Gateway.metadata.namespace }}-{{ .Gateway.metadata.name }}
        spec:
          ...
          # This resource will have its 'status.atProvider.arn' set when resource is created
          ...
      TargetGroupBinding: |
        kind: TargetGroupBinding
          ...
        spec:
          # And here we use the value 'status.atProvider.arn' from the 'LBTargetGroup' resource
          targetGroupARN: {{ (index .Resources.LBTargetGroup 0).status.atProvider.arn }}

The following figure illustrates variables available to templates, including normalization and inter-resource variables:

Template variables

Available Templating Variables

This section documents the variables that are available for templates in GatewayClassBlueprint.

The following structure is passed when rendering Gateway and HTTPRoute templates:

type TemplateValues struct {
	// Parent Gateway, always defined
	Gateway *map[string]any

	// Parent HTTPRoute. Only set when rendering HTTPRoute templates
	HTTPRoute map[string]any

	// Template values
	Values map[string]any

	// Current resources (i.e. sibling resources)
	Resources map[string]any

	// List of all hostnames across all listeners and attached
	// HTTPRoutes. These lists of hostnames are particularly
	// useful for TLS certificates which are not port specific.
	Hostnames TemplateHostnameValues
}

type TemplateHostnameValues struct {
	// Union and intersection of all hostnames across all
	// listeners and attached HTTPRoutes (with duplicates
	// removed). Intersection holds all hostnames from Union with
	// duplicates covered by wildcards removed.
	Union, Intersection []string
}

The Gateway field of the structure above holds the parent Gateway and fields can be referenced in the template as shown in the excerpt below:

  metadata:
    name: {{ .Gateway.metadata.name }}-child
    namespace: {{ .Gateway.metadata.namespace }}

Note, that if a HTTPRoute is attached to multiple Gateways (which may be using different GatewayClassBlueprint), rendering of the HTTPRoute will be done independently for each parent Gateway the HTTPRoute is attached to. The ParentRef field will contain the specific parent Gateway.