Skip to content

Reusable code/snippets #31

@fernandezcuesta

Description

@fernandezcuesta

What problem are you facing?

Inline CEL expressions might be reused by different resources in a single composition. Other functions such as function-go-templating address this with helper functions.
function-kro doesn't look to support a mechanism to reuse code.

How could this Function help solve your problem?

I can think of several options, specified by example:

Computed variables

As an example, see the following snippet where we define the ´managementPolicies´ and ´providerConfig´ once, and use it many:

input:
  apiVersion: kro.fn.crossplane.io/v1beta1
  kind: ResourceGraph
  variables:
    managementPolicies: >-
      ${schema.spec.deletionProtection
        ? ["Create", "LateInitialize", "Observe", "Update"]
        : ["Create", "Delete", "LateInitialize", "Observe", "Update"])}
    providerConfigKind: ${schema.spec.providerConfigRef.?kind.orValue("ClusterProviderConfig")}
    providerConfigName: ${schema.spec.providerConfigRef.?name.orValue("default")}
  resources:
    - id: role
      template:
        spec:
          managementPolicies: ${variables.managementPolicies}
          providerConfigRef:
            kind: ${variables.providerConfigKind}
            name: ${variables.providerConfigName}
        ...
    - ...

Registered CEL custom functions

Implementation of functions, which could be registered as CEL custom functions.

input:
  apiVersion: kro.fn.crossplane.io/v1beta1
  kind: ResourceGraph
  # List of custom functions
  functions:
    managementPolicies:
      params:
        - name: deletionProtection
          type: bool
        - name: hasImports
          type: bool
      body: >-
        deletionProtection
          ? ["Create", "LateInitialize", "Observe", "Update"]
          : ["Create", "Delete", "LateInitialize", "Observe", "Update"]
    providerConfigRef:
      params:
        - name: kind
          type: optional(string)
        - name: name
          type: optional(string)
      body:
        kind: ${kind.orValue("ClusterProviderConfig")}
        name: ${name.orValue("default")}

  resources:
    - id: role
      template:
        spec:
          managementPolicies: >-
            ${fn.managementPolicies(schema.spec.deletionProtection, has(schema.spec.imports))}
          providerConfigRef: >-
            ${fn.providerConfigRef(schema.spec.providerConfigRef.?kind, schema.spec.providerConfigRef.?name)}
          forProvider:
            ...
    - ...

or even something like the following, where after defining the functions, we might reference them for all resources in the composition:

input:
 ...
  functions: ... # same as above
  resourceDefaults:
    spec:
      managementPolicies: >-
        ${fn.managementPolicies(schema.spec.deletionProtection, has(schema.spec.imports))}
      providerConfigRef: >-
         ${fn.providerConfigRef(schema.spec.providerConfigRef.?kind, schema.spec.providerConfigRef.?name)}
  resources: ...

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions