Skip to content

Automate Configuration Validation, Changes, and Analysis with Functions

In ConfigHub, code is separate from configuration data. The code reads and/or writes configuration data.

A Function is an executable piece of code that operates on Units and Revisions.

This is a guide about how to use functions. ConfigHub supports a number of built-in functions out of the box that you may use. You may also use custom functions that execute in a worker that you build. A guide to authoring functions can be found in the SDK.

There are 3 types of Functions: Readonly, Mutating and Validating. A Readonly Function extracts or analyzes specific pieces of data from a Config Unit and returns the results. For example it may extract the container image URI from Units containing Kubernetes Deployments or other workload resource types. A Mutating function takes Config Units as input, makes changes to them, and writes and returns the mutated Units. For example, a Mutating function may update the image of Deployments and other workload types. A Validating function takes Config Units as input and returns pass/fail and failure details for each Unit. Many readonly functions start with get-, many mutating functions start with set-, and most validating functions start with vet-. Getter and Setter functions are particular subsets of readonly and mutating functions that are discussed in more detail below.

Functions are specific to a particular ToolchainType, such as Kubernetes/YAML, but there are some "standard" functions implemented in a generic way that are supported for all supported toolchains, such as get-resources and where-filter.

Discovering functions

You can use cub function list or the function browser in the UI to browse or search available functions. In the function browser you can filter by type (mutating, validating, other), toolchain, worker, name, and description text.

cub function list output looks like as follows:

cub function list --toolchain Kubernetes/YAML
TOOLCHAINTYPE      FUNCTIONNAME                      MUTATING    VALIDATING    DESCRIPTION
Kubernetes/YAML    cel-validate                      false       true          Returns true if validation expression evaluates to true for all resources
Kubernetes/YAML    compute-mutations                 false       false         Diffs the input with the config data and returns a list of mutations made to the config data
Kubernetes/YAML    delete-resource                   true        false         Remove the specified resource from the configuration data
Kubernetes/YAML    ensure-context                    true        false         Set function context values in configuration resource/element attributes (if possible) if addContext is true and remove the context if false
Kubernetes/YAML    ensure-namespaces                 true        false         Ensure every namespaced resource has a namespace field by adding one with the placeholder value if it is not present
Kubernetes/YAML    get-annotation                    false       false         Get an annotation
Kubernetes/YAML    get-attribute                     false       false         Returns values of a specified registered attribute
...

Learning how to call functions

Details of a specific function can be viewed in the function browser, or by using the cub function explain command.

For example:

cub function explain set-container-resources --toolchain Kubernetes/YAML
Usage: cub function do -- set-container-resources <container-name> <operation> <cpu> <memory> <limit-factor>

Toolchain Type             Kubernetes/YAML
Function Name              set-container-resources
Description                Set resource requests and limits for a container
Required Parameters        5
Varargs                    false
Mutating                   true
Validating                 false
Hermetic                   true
Idempotent                 true
Function Type              Custom
Attribute Name             container-resources
Affected Resource Types    apps/v1/DaemonSet, apps/v1/StatefulSet, batch/v1/Job, batch/v1/CronJob, v1/Pod, apps/v1/Deployment, apps/v1/ReplicaSet
PARAMETER    NAME              DATA-TYPE    REQUIRED    DESCRIPTION                                                                                                                                                                                                 EXAMPLE    CONSTRAINT
0            container-name    string       required    Name of the container whose resources to set                                                                                                                                                                main       ^\*|[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$
1            operation         enum         required    If "all" then requests and limits will be set unconditionally; if "cap", then the values will be set if they exceed the values; if "floor", then the values will be set if they are less than the values    all
2            cpu               string       required    Request cpu represented as a Kubernetes resource quantity, such as 500m; ignored if empty                                                                                                                   500m
3            memory            string       required    Request memory represented as a Kubernetes resource quantity, such as 256Mi; ignored if empty                                                                                                               256Mi
4            limit-factor      int          required    Integer factor to multiply requests to compute limits. A factor of 0 implies no limits.                                                                                                                     2

Notice that it displays the cub function do invocation syntax for the function, as well as descriptions of the parameters. cub function do --help displays more general help for the function do command.

The UI function browser displays similar information.

Functions that use the path registry (discussed below) register the affected resource types. You can use this to find functions applicable to your configuration unit, and also to confirm whether the functions support the resource types you want to operate on.

Invoking functions

Functions can be immediately invoked by API, CLI, or UI. They can also be used in Triggers, which is discussed next, and saved in Invocations.

The CLI has 4 ways to invoke functions:

  • cub function do: Execute a single function using positional arguments for required parameters and custom argument parsing for optional parameters rather than cub's standard flag parsing mechanism. This works with both built-in and worker functions, both on individual units and in bulk. cub function explain uses this syntax. Specify the toolchain to operate on using --toolchain. If the units are in a ChangeSet, specify the change set with --changeset. Filter the units using --where or --filter, or specify one or more specific units with --unit. Invoke triggers with --trigger and invocations with --invocation. Specify a change description with --change-desc. There a number of flags to control the output. The configuration data is not output if it is unchanged.
  • cub function exec: Execute a batch of functions from a file that are either built in or all run on the same executor. The commands use the same syntax as cub function do.
  • cub run: Execute a single function using cub's standard flag parsing mechanism, using entirely flags to specify parameter values rather than positional arguments. The function details are fetched and stored in ~/.confighub/functions.json and used to construct the command specifications. Shell completions can be generated with cub completion. Standard cub help works also. For example: cub run set-pod-defaults --help.
  • cub function local: This executes built-in functions locally in cub, for easier debugging in some cases. You could also use this to run vet-schemas before uploading your initial configuration to ConfigHub.

In the CLI it's possible to use Go templates to generate function argument values from the FunctionContext passed to the function executor. For example, to set resource names containing placeholders to names generated from Unit and Space Slugs:

cub function do set-default-names "template:{{.UnitSlug | normalizeName}}-{{.SpaceSlug | normalizeName}}"

normalizeName lowercases the string and removes characters not allowed in Kubernetes resource names. Other functions currently supported include toUpper, toLower, trimSpace, trimSuffix, and trimPrefix. The implementation can be found in the SDK.

This kind of substitution is especially useful in triggers.

cub space create home
cub trigger create --space home set-ns-name Mutation Kubernetes/YAML set-string-path v1/Namespace metadata.name "template:{{.SpaceSlug}}"
cub trigger create --space home set-ns Mutation Kubernetes/YAML set-namespace "template:{{.SpaceSlug}}"
cub trigger create --space home set-subdomain Mutation Kubernetes/YAML set-hostname "template:{{.SpaceSlug}}.local.cubby.bz"
cub trigger create --space home set-role Mutation Kubernetes/YAML set-env-var backend ROLE "template:{{.SpaceLabels.Role}}"
cub trigger create --space home set-region Mutation Kubernetes/YAML set-env-var backend REGION "template:{{.SpaceLabels.Region}}"

cub space create us-cubbychat-prod --label Environment="prod" --label Role="prod" --label Region="US" --where-trigger "Space.Slug = 'home'"

CEL expressions are similarly supported, with the prefix "cel:".

The UI also supports multiple ways and places functions can be executed:

  • Function dropdown menu in the unit list: Select units to operate on individually or specify a saved filter or an advanced filter and then select all units. Then choose a function of the appropriate toolchain type (Kubernetes/YAML for now). After execution, you can inspect results by unit. If a mutating function was executed and made changes, you can review the diffs. Results of validating functions are displayed in a table.
  • Function dropdown menu on the unit details page: You can execute functions from any tab on the unit details page. The functions are automatically filtered by the toolchain type of the unit. If the function was mutating and made a change, you can review the diff. If the function returns an AttributeValueList (discussed more below), you will be directed to the Attributes tab. You can actually make changes on that tab after clicking Edit, and then you can Save the changes. Under the covers, that calls the set-attributes function to make the changes. Note that the function menu on that page is filtered to display only functions returning AttributeValueList. You can also switch to the Function Invocations tab to view the results there. The results of Validating functions and other output types are displayed there by default.
  • Function browser: If you want to try out functions as you browse for relevant functions to do a particular task, such as setting a container image or part of one, you can invoke them from the function browser. There's a Run button on the function details drawer. You can select one or more test units, and can "dry run" mutating functions to see what they would do without permanently changing the units' configuration data.
  • Unit details dashboard apply gates mini-tab: For units with apply gates, you can re-run the validating triggers that registered the apply gates in order to view the failure details. See more on troubleshooting apply gates below.

Creating Triggers

For a comprehensive guide on creating, managing, and troubleshooting Triggers, including Apply Gates, worker behavior, and cross-Space Trigger selection, see the Validating Configuration and Enforcing Policies guide.

When creating a Trigger, you want to understand what its behavior will be on the targeted units. To preflight the behavior, filter the unit list by the trigger's ToolchainType and the trigger's space, select all of the filtered units, select the function to invoke from the dropdown menu, and choose the dry run option. Iterate on the function choice and/or argument values as necessary. When it has the outcome you expected, then save the invocation as a trigger with the same function and arguments in the desired space.

To create some basic triggers you will probably want with the CLI you can do:

cub space create home
cub trigger create --space home valid-k8s Mutation Kubernetes/YAML vet-schemas
cub trigger create --space home complete-k8s Mutation Kubernetes/YAML vet-placeholders
cub trigger create --space home context-k8s Mutation Kubernetes/YAML ensure-context true

Then when creating other spaces, you can refer to them:

homeSpaceID="$(cub space get home --jq '.Space.SpaceID')"
cub space create myspace --label Environment=dev --where-trigger "SpaceID = '$homeSpaceID'"

Troubleshooting Apply Gates and Apply Warnings

Validating Triggers record Apply Gates on Units when the validating function does not pass. Triggers with Warn set to true record Apply Warnings instead, which are non-blocking. Both are shown on the unit details Dashboard tab, Apply Gates mini-tab. You can re-run triggers there in order to see the failure details. For vet-placeholders, you can invoke get-placeholders and will then be directed to the Attributes tab, where you can make changes to the values and save them.

To create a trigger that produces warnings instead of blocking gates:

cub trigger create --space home replicas-check Mutation Kubernetes/YAML --warn vet-celexpr 'r.kind != "Deployment" || r.spec.replicas > 1'

To convert an existing warning trigger to blocking, or vice versa:

cub trigger update --space home replicas-check --unwarn
cub trigger update --space home replicas-check --warn

Apply Warnings are visible in the CLI via cub unit get and can be filtered with --where "LEN(ApplyWarnings) > 0".

Frequently used functions

At the moment, the built-in functions target resources primarily by type rather than by name in order to keep their arguments simple and concise. This works well with granular, focused units, such as a single Kubernetes Deployment + Service + Ingress, as opposed to units containing large blobs of configuration.

Validating Functions

Validating functions are especially useful for Triggers.

  • vet-schemas: Schema validation using kubeconform. We recommend you always install this as a trigger.
  • vet-placeholders: Verify no placeholder values remain. We recommend you always install this as a trigger.
  • vet-approvedby COUNT: Check if the required number of approvals exist. Install this as a trigger if you want to require review and approval.
  • vet-celexpr EXPRESSION: Custom CEL validation expressions. Use this as a trigger to create custom constraints for different environments.

Readonly Functions

  • get-placeholders: Find placeholder values ("confighubplaceholder" or 999999999) that need replacement
  • get-resources: List all resources and their types. Use none for the body parameter if you just want the resource types and names.
  • get-image CONTAINER_NAME: Extract the image of a named container or all containers (*)
  • get-replicas: Extract the replicas count from Kubernetes workload resources
  • get-env-var CONTAINER_NAME VAR: Get the value of an environment variable of a container
  • yq EXPRESSION: Apply yq queries to YAML configuration

The following functions can be used as fallbacks for cases lacking more specific functions. Path syntax is discussed in more detail below. For Kubernetes/YAML, resource types are in group/version/kind format.

  • get-string-path RESOURCE_TYPE PATH: Extract string values from a specified path pattern
  • get-int-path RESOURCE_TYPE PATH: Extract integer values from a specified path pattern
  • get-bool-path RESOURCE_TYPE PATH: Extract boolean values from a specified path pattern

Mutating Functions

  • set-image CONTAINER_NAME IMAGE: Update container images; useful for changing the container image registry, repo, and reference all at once
  • set-image-reference CONTAINER_NAME REFERENCE: Update container tags (prefix the reference with :) and digests (prefix the reference with @) by container name; useful for updating a specific container's image
  • set-image-reference-by-uri URI REFERENCE: Update container tags and digests for a specified container image; useful for regular release pushes of an image
  • set-image-registry-by-registry ORIGINAL_REGISTRY_PREFIX NEW_REGISTRY_PREFIX: Update container registry prefixes; useful for switching to a mirror registry
  • set-replicas COUNT: Set replica counts for workloads
  • set-env-var CONTAINER_NAME VAR VALUE: Set an environment variable of a container
  • set-namespace NAMESPACE: Set namespace for all namespaced resources in units
  • set-container-resources CONTAINER_NAME OPERATION CPU_REQUEST MEMORY_REQUEST LIMIT_FACTOR: Set resource requests and limits for a container. If "all" then requests and limits will be set unconditionally; if "cap", then the values will be set if they exceed the values; if "floor", then the values will be set if they are less than the values or if there are no requests or limits. The cpu and memory request values use Kubernetes resource quantity syntax, such as 250m. The limit factor is multiplied by the requests to compute limits. A factor of 0 implies no limits.
  • set-pod-defaults --pod-security=true/false --automount-service-account-token=true/false --security-context=true/false --resources=true/false --probes=true/false: Sets a number of best-practice pod and container properties. The probe values are set to default values that you can change after the fields are added. If you want to set specific resource request and limit values, use set-container-resources instead of --resources=true.
  • set-annotation KEY VALUE: Add/update an annotation for all resources in units
  • set-label KEY VALUE: Add/update a label for all resources in units
  • search-replace SEARCH REPLACE: Text replacement across configuration

The following functions can be used as fallbacks for cases lacking more specific functions.

  • set-string-path RESOURCE_TYPE PATH VALUE: Set a string value at a specified path pattern
  • set-int-path RESOURCE_TYPE PATH VALUE: Set a integer value at a specified path pattern
  • set-bool-path RESOURCE_TYPE PATH VALUE: Set a boolean value at a specified path pattern

Configuration path syntax

Resource paths sometimes need to be specified, such as in the set-*-path and get-*-path functions.

Configuration paths are dot-separated, including for array indices. For example: spec.template.spec.containers.0.image. Dots are escaped with ~1. (That syntax comes from the JSON Pointer RFC.)

The Kubernetes API and cloud APIs contain a number of associative lists, such as container lists and environment variable lists, where the keys identifying the array elements are map elements of the array element, such as name. The syntax for an associative list path matching is .?<map key>=<map value> in place of the array index, as in spec.template.spec.containers.?name=main.image.

Wildcards are also supported for array indices and/or map keys by some functions. For example, spec.template.spec.containers.*.image and metadata.annotations.confighub~1com/RevisionNum.

Getters and setters, attributes, and the path registry

To change a specific configuration value, you could use a function like set-int-path and specify the configuration path as a function argument, but if you operate on the same path(s) frequently, it can be worthwhile to define a function so that your users don't need to type or remember the paths and the associative matching syntax.

A number of functions, primarily those of type PathVisitor, work by registering the appropriate configuration paths of the relevant resource types for the values they operate on, using an approach similar to kustomize.

The Function Executor maintains a Path Registry that associates a set of paths and path metadata with a named Attribute used to identify that set of semantically related paths. Simple getter and setter functions like get-replicas and set-replicas operate on a single attribute, replicas in this case, which is reported by the function metadata displayed by cub function explain. There's a universal getter, get-attribute, which can be used to get values for an Attribute by name.

The Attribute entity

Attributes, paths, and getters and setters can also be defined by API, by creating Attributes.

Example 1: Creating a custom attribute for cert-manager Certificate secretName

Suppose you want ConfigHub to track the spec.secretName field in cert-manager Certificate resources. Create a YAML definition file:

# cert-secret-name.yaml
Slug: cert-secret-name
ToolchainType: Kubernetes/YAML
DataType: string
Description: Tracks the secretName field in cert-manager Certificate resources
ResourceTypePaths:
  - ResourceType: cert-manager.io/v1/Certificate
    Paths:
      spec.secretName:
        Path: spec.secretName
        AttributeName: cert-secret-name
        DataType: string
Parameters:
  - ParameterName: secret-name
    Required: true
    Description: Name of the TLS secret
    DataType: string

Create the attribute:

cub attribute create --space my-space --filename cert-secret-name.yaml

After creation, the functions get-cert-secret-name and set-cert-secret-name are available in the Space. You can use them in triggers or invoke them directly.

Example 2: Adding resource-name paths for Istio VirtualService

To extend ConfigHub's needs/provides dependency resolution to Istio VirtualService resources, create an attribute that registers paths where service references appear:

# istio-resource-name.yaml
Slug: resource-name
ToolchainType: Kubernetes/YAML
DataType: string
Description: Extends resource-name tracking to Istio VirtualService
ResourceTypePaths:
  # VirtualService needs Service references via destination.host
  - ResourceType: networking.istio.io/v1/VirtualService
    Paths:
      spec.http.*.route.*.destination.host:
        Path: spec.http.*.route.*.destination.host
        AttributeName: resource-name
        DataType: string
        IsNeeded: true
    SetterInvocation:
      FunctionName: set-references-of-type
      Arguments:
        - ParameterName: resource-type
          Value: v1/Service
cub attribute create --space my-space --filename istio-resource-name.yaml

Now ConfigHub can automatically detect which Services an Istio VirtualService references, enabling dependency-aware operations like sequenced rollouts.

Note: For resource-name attributes, entries with IsNeeded: true require a SetterInvocation using set-references-of-type, and entries with IsProvided: true require a GetterInvocation using get-resources-of-type. The same resource type can appear in multiple entries with different invocations. See the AWS ACK example below for a complete multi-resource-type configuration.

Example 3: Extending container-image to a custom CRD

If you have a custom CRD (e.g., MLModel/ml.example.com/v1) with a container image field, extend the container-image attribute:

# ml-container-image.yaml
Slug: container-image
ToolchainType: Kubernetes/YAML
DataType: string
Description: Extends container-image tracking to MLModel CRD
ResourceTypePaths:
  - ResourceType: ml.example.com/v1/MLModel
    Paths:
      spec.serving.image:
        Path: spec.serving.image
        AttributeName: container-image
        DataType: string
Parameters:
  - ParameterName: container-name
    Required: true
    Description: Name of the container whose image to set
    DataType: string
  - ParameterName: container-image
    Required: true
    Description: Full container image
    DataType: string
cub attribute create --space my-space --filename ml-container-image.yaml

Example 4: AWS ACK resource-name with multiple resource types

This example demonstrates a complete resource-name attribute for AWS ACK custom resources, showing how a single attribute can register needs/provides paths across multiple resource types. Each resource type can appear multiple times when it references different upstream resource types.

Slug: resource-name
ToolchainType: Kubernetes/YAML
DataType: string
ResourceTypePaths:
  # VPC provides metadata.name
  - ResourceType: services.k8s.aws/v1alpha1/VPC
    Paths:
      metadata.name:
        Path: metadata.name
        AttributeName: resource-name
        DataType: string
        IsProvided: true
    GetterInvocation:
      FunctionName: get-resources-of-type
      Arguments:
        - ParameterName: resource-type
          Value: services.k8s.aws/v1alpha1/VPC
  # Subnet provides metadata.name
  - ResourceType: services.k8s.aws/v1alpha1/Subnet
    Paths:
      metadata.name:
        Path: metadata.name
        AttributeName: resource-name
        DataType: string
        IsProvided: true
    GetterInvocation:
      FunctionName: get-resources-of-type
      Arguments:
        - ParameterName: resource-type
          Value: services.k8s.aws/v1alpha1/Subnet
  # Subnet needs VPC references
  - ResourceType: services.k8s.aws/v1alpha1/Subnet
    Paths:
      spec.vpcRef.from.name:
        Path: spec.vpcRef.from.name
        AttributeName: resource-name
        DataType: string
        IsNeeded: true
    SetterInvocation:
      FunctionName: set-references-of-type
      Arguments:
        - ParameterName: resource-type
          Value: services.k8s.aws/v1alpha1/VPC
  # Subnet needs RouteTable references
  - ResourceType: services.k8s.aws/v1alpha1/Subnet
    Paths:
      spec.routeTableRefs.*.from.name:
        Path: spec.routeTableRefs.*.from.name
        AttributeName: resource-name
        DataType: string
        IsNeeded: true
    SetterInvocation:
      FunctionName: set-references-of-type
      Arguments:
        - ParameterName: resource-type
          Value: services.k8s.aws/v1alpha1/RouteTable
cub attribute create --space my-space --from-stdin resource-name Kubernetes/YAML string < ack-resource-name.yaml

With this attribute, linking a Subnet unit to a VPC unit with --update-type NeedsProvides --auto-update will automatically resolve spec.vpcRef.from.name to the VPC's metadata.name.

Example 5: Defaults attribute for container resource requests

A defaults attribute uses the $visitor setter invocation to embed default values directly in the path definitions. ConfigHub applies these defaults only to fields that still contain placeholder values, leaving intentionally configured values untouched.

# resource-defaults.yaml
Slug: resource-defaults
ToolchainType: Kubernetes/YAML
DataType: string
Description: Default CPU and memory requests for containers
ResourceTypePaths:
  - ResourceType: apps/v1/Deployment
    Paths:
      spec.template.spec.containers.*.resources.requests.cpu:
        Path: spec.template.spec.containers.*.resources.requests.cpu
        AttributeName: resource-defaults
        DataType: string
        Details:
          SetterInvocations:
            - FunctionName: "$visitor"
              Arguments:
                - Value: "100m"
      spec.template.spec.containers.*.resources.requests.memory:
        Path: spec.template.spec.containers.*.resources.requests.memory
        AttributeName: resource-defaults
        DataType: string
        Details:
          SetterInvocations:
            - FunctionName: "$visitor"
              Arguments:
                - Value: "128Mi"
cub attribute create --space my-space --from-stdin resource-defaults Kubernetes/YAML string < resource-defaults.yaml

This registers three functions:

  • get-resource-defaults — reads current values at all registered paths
  • set-resource-defaults — applies defaults only where placeholders exist
  • vet-resource-defaults — validates that current values match the expected defaults

The set-resource-defaults function takes no value arguments. To apply defaults to a unit:

cub function do --space my-space --where "Slug = 'my-deploy'" set-resource-defaults

Common output types

Standard function output types used by built-in functions are defined in the function API in the SDK. The most common output types are ValidationResultList and AttributeValueList.

Validating functions return the ValidationResultList type. In Go, ValidationResult is currently:

type ValidationResult struct {
    Passed           bool               // true if valid, false otherwise
    Index            int                // index of the function invocation corresponding to the result
    Details          []string           `json:",omitempty"` // optional list of failure details
    FailedAttributes AttributeValueList `json:",omitempty"` // optional list of failed attributes; preferred over Details
}

Value-extracting functions, such as getters, return the AttributeValueList type, which is defined as follows. It contains the Value, Path, resource metadata, and Attribute metadata from the Path Registry.

// AttributeValue provides the value of an attribute in addition to information about the attribute.
type AttributeValue struct {
    AttributeInfo
    Value   any
    Comment string `json:",omitempty"`
    Index   int    // index of the function invocation corresponding to the result
}

// AttributeInfo conveys both the identifying information about a resource attribute and its
// metadata.
type AttributeInfo struct {
    AttributeIdentifier
    AttributeMetadata
}

// An AttributeIdentifier identifies the resource type and name and resolved path of the
// resource attribute.
type AttributeIdentifier struct {
    ResourceInfo
    Path        ResolvedPath `swaggertype:"string"`
    InLiveState bool         `json:",omitempty"`
}

// AttributeMetadata specifies the AttributeName, DataType, and other details, such as corresponding
// getter and setter functions for the attribute.
type AttributeMetadata struct {
    AttributeName AttributeName     `json:",omitempty" swaggertype:"string"`
    DataType      DataType          `swaggertype:"string"`
    Info          *AttributeDetails `json:",omitempty"`
}

// ResourceInfo contains the ResourceName, ResourceNameWithoutScope, ResourceType, and ResourceCategory for a configuration Element within a configuration Unit.
type ResourceInfo struct {
    ResourceName             ResourceName     `swaggertype:"string" description:"Name of a resource in the system under management represented in the configuration data; Kubernetes resources are represented in the form <metadata.namespace>/<metadata.name>; not all ToolchainTypes necessarily use '/' as a separator between any scope(s) and name or other client-chosen ID"`
    ResourceNameWithoutScope ResourceName     `swaggertype:"string" description:"Name of a resource in the system under management represented in the configuration data, without any uniquifying scope, such as Namespace, Project, Account, Region, etc.; Kubernetes resources are represented in the form <metadata.name>"`
    ResourceType             ResourceType     `swaggertype:"string" description:"Type of a resource in the system under management represented in the configuration data; Kubernetes resources are represented in the form <apiVersion>/<kind> (aka group-version-kind)"`
    ResourceCategory         ResourceCategory `json:",omitempty" swaggertype:"string" description:"Category of configuration element represented in the configuration data; Kubernetes and OpenTofu resources are of category Resource, and application configuration files are of category AppConfig"`
}