vcf-services

Building Environment-Aware Supervisor Services

When developing a Supervisor Service, your application often needs to know about the environment it’s running in (e.g., “Does this Supervisor expose a particular platform capability?” or “How large are the control plane nodes?”).

Developers can bind their declared Package inputs to well-known properties published in the SupervisorProperties custom resource. The Supervisor injects these values into your service at runtime and updates your deployed application when any of them change.

Implementation: From Schema to Runtime

Step A: Declare the Property

In your Package definition, add the specific keys to valuesSchema. The key names must match those exposed by the SupervisorProperties API (see the Reference table below). In this example we use virtualIP (the Virtual IP used to access the Supervisor API).

apiVersion: data.packaging.carvel.dev/v1alpha1
kind: Package
metadata:
  name: my-service.example.com
  # namespace, etc.
spec:
  valuesSchema:
    openAPIv3:
      type: object
      additionalProperties: false
      properties:
        virtualIP:  # Supervisor injects the cluster Virtual IP here
          type: string
          description: "Virtual IP of the LoadBalancer fronting the Supervisor API."
          default: ""

Step B: Consume the Property in your Workload

Once a property is declared in valuesSchema, the platform makes it available as data.values.<propertyName> to ytt at templating time. There are two correct patterns for getting that value into your running container, and the right choice depends on whether you own the workload manifest.

ytt syntax reminder. Directives must start with #@ followed by a space (for example, #@ load("@ytt:data", "data")). Without the space, ytt treats the line as a normal YAML comment and your template will not execute.

Pattern 1 — preferred: reference data.values directly in your Deployment source

If you author your own manifests, the cleanest pattern is to reference data.values inline in the Deployment. No overlay needed.

#@ load("@ytt:data", "data")
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-controller
  namespace: #@ data.values.namespace
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: my-controller
  template:
    metadata:
      labels:
        app.kubernetes.io/name: my-controller
    spec:
      containers:
        - name: manager
          image: my-registry.example.com/my-controller:1.0.0
          env:
            - name: APISERVER_LB_VIRTUAL_IP
              value: #@ data.values.virtualIP

Notes:

Pattern 2 — overlay: inject the env var into a Deployment you don’t own

Use this when the Deployment is rendered from upstream YAML (Helm output, a third-party operator manifest you don’t want to fork, etc.) and you only want to add an env var on top.

#@ load("@ytt:overlay", "overlay")
#@ load("@ytt:data", "data")

#@overlay/match by=overlay.subset({"kind": "Deployment", "metadata": {"name": "my-controller"}}), expects=1
---
spec:
  template:
    spec:
      containers:
        #@overlay/match by=overlay.subset({"name": "manager"})
        - name: manager
          #@overlay/match missing_ok=True
          env:
            #@overlay/append
            - name: APISERVER_LB_VIRTUAL_IP
              value: #@ data.values.virtualIP

Why each annotation matters:

If you want to inject the same env var into several containers (e.g. a sidecar pattern), match all containers and append into each one:

        #@overlay/match by=overlay.all, expects="1+"
        -
          #@overlay/match missing_ok=True
          env:
            #@overlay/append
            - name: APISERVER_LB_VIRTUAL_IP
              value: #@ data.values.virtualIP

Tips that apply to both patterns

Reference: Supported Properties

The following properties are currently exposed by the API. If your service requires a property not listed here, it may require a newer version of the Supervisor.

Property Type Description
apiServerDNSNames array of string API server DNS names associated with the Supervisor.
capabilities array of object Capabilities the Supervisor has (e.g. vCenter-supported features). Each item has name (string) and value (boolean).
controlPlaneCount integer Number of control planes enabled on the Supervisor.
controlPlaneResources object Resource footprint of the control plane VM: cpuCount (integer), memoryMiB (integer).
cpVMSize string Deprecated. Use controlPlaneResources instead. Control plane size: TINY, SMALL, MEDIUM, or LARGE.
namespacesCLIPluginVersion string Supervisor-recommended namespaces CLIPlugin CR version.
networkProvider string Network provider used on the Supervisor (e.g. NSX, nsx-vpc, or vsphere-network).
podVMSupported boolean Whether the Supervisor supports vSphere Pods.
ssoDomain string Name of the default SSO domain configured in vCenter.
stretchedSupervisor boolean Whether the Supervisor is enabled on a set of vSphere Zones.
supervisorUUID string Instance ID of the Supervisor.
vCenterTrustBundle string Base64-encoded vCenter trusted root certificates in PEM format.
vCenterUUID string UUID of the vCenter.
vcPNID string Primary Network Identifier of vCenter.
vcPort string Port of vCenter.
vcPublicKeys string Base64-encoded vCenter OIDC issuer, client audience, and public keys in JWKS format.
virtualIP string IP address of the Kubernetes LoadBalancer type service fronting the API servers.