Module
The Module resource represents an installable component or application that can be deployed into a Workspace. Modules can deploy Helm charts or run custom containerized modules, and support hibernation to reduce resource consumption.
API Group and Version
Section titled “API Group and Version”- API Group:
batch.forkspacer.com - API Version:
v1 - Kind:
Module - Short Name:
mo
Example
Section titled “Example”Helm Module Example
Section titled “Helm Module Example”apiVersion: batch.forkspacer.com/v1kind: Modulemetadata: name: redis namespace: default
config: - name: "Redis Version" alias: "version" option: editable: true required: false default: "21.2.9" values: - "21.2.9" - "21.2.7" - "21.2.6"
- name: "Replica Count" alias: "replicaCount" integer: editable: true required: false default: 1 min: 0 max: 5
spec: helm: chart: repo: url: https://charts.bitnami.com/bitnami chart: redis version: "{{.config.version}}"
namespace: default
values: - raw: replica: replicaCount: "{{.config.replicaCount}}" image: repository: bitnamilegacy/redis global: security: allowInsecureImages: true
cleanup: removePVCs: true
workspace: name: dev-environment namespace: default
hibernated: false
config: version: "21.2.7" replicaCount: 1Custom Module Example
Section titled “Custom Module Example”apiVersion: batch.forkspacer.com/v1kind: Modulemetadata: name: custom-app namespace: default
spec: custom: image: my-registry/custom-app:v1.0.0 permissions: - workspace
workspace: name: dev-environment namespace: default
hibernated: falseSpec Fields
Section titled “Spec Fields”The .spec field defines the desired state of the Module.
| Field | Type | Description | Required |
|---|---|---|---|
helm | object | Helm chart deployment configuration. See Helm. | No (mutually exclusive with custom) |
custom | object | Custom module configuration for containerized HTTP services. See Custom. | No (mutually exclusive with helm) |
workspace | object | Reference to the workspace where this module should be deployed. See WorkspaceReference. | Yes |
config | object | User-provided configuration values (arbitrary key-value pairs). | No |
hibernated | boolean | Whether the module should be in hibernated state. | No (default: false) |
Note: Either helm or custom must be specified, but not both.
Config Fields
Section titled “Config Fields”The top-level config array defines user-configurable parameters with validation rules. Each configuration item specifies:
- name: Human-readable configuration name
- alias: The key used in
spec.configto provide values - Type-specific spec: One of:
string,integer,boolean,option, ormultipleOptions
Configuration Types
Section titled “Configuration Types”String Configuration
Section titled “String Configuration”config: - name: "Database Host" alias: "dbHost" string: required: true default: "localhost" regex: "^[a-zA-Z0-9.-]+$" editable: trueFields:
required(boolean): Whether the field is requireddefault(string): Default valueregex(string): Validation regex patterneditable(boolean): Whether users can modify this value
Integer Configuration
Section titled “Integer Configuration”config: - name: "Replicas" alias: "replicas" integer: required: true default: 1 min: 1 max: 10 editable: trueFields:
required(boolean): Whether the field is requireddefault(integer): Default valuemin(integer): Minimum allowed valuemax(integer): Maximum allowed valueeditable(boolean): Whether users can modify this value
Boolean Configuration
Section titled “Boolean Configuration”config: - name: "Enable Metrics" alias: "metrics" boolean: required: false default: false editable: trueFields:
required(boolean): Whether the field is requireddefault(boolean): Default valueeditable(boolean): Whether users can modify this value
Option Configuration (Single Selection)
Section titled “Option Configuration (Single Selection)”config: - name: "Environment" alias: "env" option: required: true default: "development" values: - development - staging - production editable: trueFields:
required(boolean): Whether the field is requireddefault(string): Default value (must be in values list)values(array): List of allowed valueseditable(boolean): Whether users can modify this value
Multiple Options Configuration
Section titled “Multiple Options Configuration”config: - name: "Features" alias: "features" multipleOptions: required: false default: - logging values: - logging - metrics - tracing - profiling min: 1 max: 3 editable: trueFields:
required(boolean): Whether the field is requireddefault(array): Default values (must be in values list)values(array): List of allowed valuesmin(integer): Minimum number of selectionsmax(integer): Maximum number of selectionseditable(boolean): Whether users can modify this value
Using Configuration Values
Section titled “Using Configuration Values”Configuration values defined in the config array are provided by users in spec.config and can be referenced in Helm values or custom module configurations using Go templates:
spec: helm: values: - raw: replicaCount: "{{.config.replicas}}" environment: "{{.config.env}}" config: replicas: 3 env: "production"The helm field specifies Helm chart deployment configuration.
| Field | Type | Description | Required |
|---|---|---|---|
chart | object | Helm chart source specification. See Chart. | Yes |
namespace | string | Target Kubernetes namespace for the Helm release. Supports templating. | Yes |
releaseName | string | Custom Helm release name (DNS-1035 compliant). Auto-generated if not specified. Immutable after creation. See Release Names. | No |
existingRelease | object | Reference to an existing Helm release to adopt. See ExistingRelease. | No |
values | array | Array of value sources (raw, file, configMap). | No |
outputs | array | Output values to expose after installation. | No |
cleanup | object | Cleanup behavior when module is deleted. | No |
migration | object | Data migration configuration for workspace forking. | No |
The chart field specifies where the Helm chart should be loaded from. Only one source type should be specified.
| Field | Type | Description | Required |
|---|---|---|---|
repo | object | Helm chart repository source. See ChartRepo. | No |
git | object | Git repository source. See ChartGit. | No |
configMap | object | ConfigMap containing the chart archive. See ChartConfigMap. | No |
ChartRepo
Section titled “ChartRepo”Deploy a chart from a Helm repository:
spec: helm: chart: repo: url: https://charts.bitnami.com/bitnami chart: redis version: "21.2.9" auth: # Optional for private repositories name: registry-credentials namespace: default| Field | Type | Description | Required |
|---|---|---|---|
url | string | Helm chart repository URL | Yes |
chart | string | Name of the chart in the repository | Yes |
version | string | Chart version to install. Supports templating. | No |
auth | object | Authentication credentials for private repositories | No |
auth.name | string | Name of the Secret containing credentials | Yes (if auth specified) |
auth.namespace | string | Namespace of the Secret | No (default: default) |
ChartGit
Section titled “ChartGit”Deploy a chart from a Git repository:
spec: helm: chart: git: repo: https://github.com/org/charts-repo path: /charts/myapp revision: main auth: # Optional for private repositories httpsSecretRef: name: git-credentials namespace: default| Field | Type | Description | Required |
|---|---|---|---|
repo | string | Git repository URL (https or ssh) | Yes |
path | string | Path to the chart directory containing Chart.yaml | No (default: /) |
revision | string | Git revision (branch, tag, commit SHA) | No (default: main) |
auth | object | Authentication for private repositories | No |
auth.httpsSecretRef | object | Reference to Secret with username and token fields | No |
ChartConfigMap
Section titled “ChartConfigMap”Deploy a chart from a ConfigMap:
spec: helm: chart: configMap: name: redis-chart namespace: default key: chart.tgz| Field | Type | Description | Required |
|---|---|---|---|
name | string | Name of the ConfigMap | Yes |
namespace | string | Namespace of the ConfigMap | No (default: default) |
key | string | Key containing the chart archive (.tgz file) | No (default: chart.tgz) |
Release Names
Section titled “Release Names”The releaseName field allows you to specify a custom name for the Helm release. If not specified, Forkspacer automatically generates a unique release name.
Auto-generated Release Names:
When releaseName is not provided, the operator automatically generates a unique release name using the format:
<namespace>-<11-character-uuid>For example: default-a1b2c3d4e5f
Custom Release Names:
You can specify a custom release name that must comply with DNS-1035 label standards:
- Start with a lowercase letter
- Contain only lowercase letters, numbers, and hyphens
- End with a lowercase letter or number
- Be 63 characters or less
spec: helm: releaseName: my-custom-release chart: repo: url: https://charts.bitnami.com/bitnami chart: redis namespace: defaultImportant Notes:
- The
releaseNamefield is immutable after the Module is created - Once set (either automatically or manually), it cannot be changed
- When adopting an existing release with
existingRelease, the release name comes fromexistingRelease.nameinstead
ExistingRelease
Section titled “ExistingRelease”The existingRelease field allows you to adopt and track existing Helm releases without reinstalling them.
spec: helm: existingRelease: name: redis namespace: default| Field | Type | Description | Required |
|---|---|---|---|
name | string | Name of the existing Helm release | Yes |
namespace | string | Namespace where the Helm release is installed | No (default: default) |
Important: When a Module with an adopted Helm release is deleted, the underlying Helm release is not uninstalled. The Module only detaches from the release, leaving it running in the cluster.
Helm Values
Section titled “Helm Values”The values field accepts an array of value sources. Multiple sources can be specified and will be merged in order.
Raw Values
Section titled “Raw Values”Inline YAML values with template support:
spec: helm: values: - raw: replicaCount: "{{.config.replicas}}" image: tag: "{{.config.imageTag}}"File Values
Section titled “File Values”HTTP/HTTPS URL to a values file:
spec: helm: values: - file: https://example.com/helm-values/my-values.yamlConfigMap Values
Section titled “ConfigMap Values”Reference to a ConfigMap containing values:
spec: helm: values: - configMap: name: helm-values namespace: default key: values.yaml # Optional, defaults to "values.yaml"| Field | Type | Description | Required |
|---|---|---|---|
name | string | Name of the ConfigMap | Yes |
namespace | string | Namespace of the ConfigMap | No (default: default) |
key | string | Key containing the values YAML | No (default: values.yaml) |
The values must be stored under the specified key (default: values.yaml) in the ConfigMap’s data.
Helm Outputs
Section titled “Helm Outputs”Outputs allow you to expose values from the Helm release:
spec: helm: outputs: - name: "Redis Password" valueFrom: secret: name: "{{.releaseName}}" key: redis-password namespace: default - name: "Redis Endpoint" value: "redis-master.default.svc.cluster.local:6379"Helm Cleanup
Section titled “Helm Cleanup”Configure cleanup behavior when the module is deleted:
spec: helm: cleanup: removeNamespace: false removePVCs: trueHelm Migration
Section titled “Helm Migration”Configure data migration for workspace forking:
spec: helm: migration: pvcs: - "redis-data-{{.releaseName}}-master-0" secrets: - "{{.releaseName}}" configMaps: - "{{.releaseName}}-config"Custom
Section titled “Custom”The custom field specifies a custom containerized module that implements an HTTP API for lifecycle management.
| Field | Type | Description | Required |
|---|---|---|---|
image | string | Docker image reference (e.g., my-registry/my-module:v1.0.0) | Yes |
imagePullSecrets | array of strings | List of Kubernetes secret names for pulling private images | No |
permissions | array of strings | Cluster access permissions: workspace or controller | No |
Example:
spec: custom: image: my-registry/app-installer:v1.0.0 imagePullSecrets: - my-registry-secret permissions: - workspacePermissions
Section titled “Permissions”workspace: Provides the module with the kubeconfig file of the target workspacecontroller: Provides access to the main cluster via a service account (use with caution)
WorkspaceReference
Section titled “WorkspaceReference”The workspace field references the target workspace where the module will be deployed.
| Field | Type | Description | Required |
|---|---|---|---|
name | string | Name of the target workspace | Yes |
namespace | string | Namespace of the target workspace | No (default: default) |
Example:
spec: workspace: name: production-workspace namespace: prodStatus Fields
Section titled “Status Fields”The .status field reflects the observed state of the Module.
| Field | Type | Description |
|---|---|---|
phase | string | Current phase: ready, installing, uninstalling, sleeping, sleeped, resuming, failed |
lastActivity | string (date-time) | Timestamp of the last activity |
message | string | Human-readable message about the current state |
source | string | Source type of the module (e.g., helm, custom) |
conditions | array | Standard Kubernetes conditions |
Conditions
Section titled “Conditions”Standard Kubernetes condition types:
- Available: The module is fully functional and running
- Progressing: The module is being installed, updated, or transitioning
- Degraded: The module failed to reach or maintain its desired state
Usage Examples
Section titled “Usage Examples”Helm Module from Repository
Section titled “Helm Module from Repository”apiVersion: batch.forkspacer.com/v1kind: Modulemetadata: name: postgresql namespace: default
config: - name: "Storage Size" alias: "storageSize" string: required: false default: "10Gi" regex: "^[0-9]+(Mi|Gi|Ti)$"
spec: helm: chart: repo: url: https://charts.bitnami.com/bitnami chart: postgresql version: "14.0.0"
namespace: default
values: - raw: persistence: size: "{{.config.storageSize}}"
workspace: name: dev-environment
config: storageSize: "20Gi"Helm Module from Git
Section titled “Helm Module from Git”apiVersion: batch.forkspacer.com/v1kind: Modulemetadata: name: my-app namespace: default
spec: helm: chart: git: repo: https://github.com/myorg/charts path: /charts/myapp revision: v1.0.0
namespace: default
workspace: name: dev-environmentHelm Module with Custom Release Name
Section titled “Helm Module with Custom Release Name”apiVersion: batch.forkspacer.com/v1kind: Modulemetadata: name: my-redis namespace: default
spec: helm: releaseName: prod-redis-primary # Custom release name
chart: repo: url: https://charts.bitnami.com/bitnami chart: redis version: "21.2.9"
namespace: default
values: - raw: fullnameOverride: "{{.releaseName}}" # Uses the custom name
workspace: name: production-workspaceThis Module uses a custom release name instead of the auto-generated one. The releaseName is immutable after creation.
Adopting an Existing Helm Release
Section titled “Adopting an Existing Helm Release”apiVersion: batch.forkspacer.com/v1kind: Modulemetadata: name: existing-redis namespace: default
spec: helm: chart: repo: url: https://charts.bitnami.com/bitnami chart: redis version: "21.2.9"
existingRelease: name: redis namespace: default
namespace: default
workspace: name: production-workspaceThis Module will track the existing redis Helm release without reinstalling it. When existingRelease is set, the release name comes from existingRelease.name.
Custom Module
Section titled “Custom Module”apiVersion: batch.forkspacer.com/v1kind: Modulemetadata: name: custom-installer namespace: default
config: - name: "Environment" alias: "env" option: required: true default: "development" values: - development - staging - production
spec: custom: image: my-registry/installer:v1.0.0 permissions: - workspace
workspace: name: dev-environment
config: env: "production"Hibernating a Module
Section titled “Hibernating a Module”apiVersion: batch.forkspacer.com/v1kind: Modulemetadata: name: api-service namespace: default
spec: helm: chart: repo: url: https://charts.example.com chart: api-service version: "1.0.0"
namespace: default
workspace: name: dev-environment
hibernated: trueModule Lifecycle
Section titled “Module Lifecycle”-
Installation: When a Module is created, the operator processes either the Helm chart or custom module based on the spec.
-
Configuration: The
configfield provides user-supplied values that are validated against the configuration schema. -
Hibernation: Setting
hibernated: truescales down the module’s resources to reduce costs while preserving configuration. -
Updates: Modifying the Module spec triggers an update in the workspace.
-
Deletion: Deleting a Module resource triggers uninstallation (except for adopted Helm releases).
Spec Rendering and Templating
Section titled “Spec Rendering and Templating”The Module CRD supports powerful Go template rendering for both Helm and Custom module specs. The operator processes templates before deploying resources, enabling dynamic configuration based on validated user input.
How Rendering Works
Section titled “How Rendering Works”When a Module is processed, the operator:
- Validates Configuration: Validates user-provided
spec.configvalues against theconfigschema - Determines Release Name (Helm only): Uses the configured
releaseNameif provided, or the auto-generated unique name (format:<namespace>-<11-char-uuid>). For adopted releases, usesexistingRelease.name. - Renders Namespace (Helm only): Renders the namespace field first with available context
- Renders Spec: Recursively processes the entire spec, replacing template expressions with actual values
- Type Preservation: Automatically converts numeric and boolean strings to their proper types
Template Context
Section titled “Template Context”Helm Modules
Section titled “Helm Modules”Available template variables in Helm specs:
.config.<alias>: User-provided configuration values (validated).releaseName: The Helm release name - either custom-specified viareleaseNamefield, auto-generated (e.g.,default-a1b2c3d4e5f), or fromexistingRelease.namefor adopted releases.namespace: Rendered namespace value (available in all fields except namespace itself)
Custom Modules
Section titled “Custom Modules”Available template variables in Custom specs:
.config.<alias>: User-provided configuration values (validated)
Template Syntax
Section titled “Template Syntax”Templates use Go’s text/template syntax with {{ and }} delimiters.
Basic Substitution:
image: "myregistry/app:{{.config.version}}"Conditional Logic:
enabled: "{{ if eq .config.environment \"production\" }}true{{ else }}false{{ end }}"String Manipulation:
serviceName: "{{ .releaseName | lower }}-svc"Default Values:
storageClass: "{{ default \"standard\" .config.storageClass }}"Numeric Operations:
maxConnections: "{{ mul .config.replicas 10 }}"Template Functions
Section titled “Template Functions”In addition to Go’s standard template functions (like default, eq, gt, mul, etc.), Forkspacer provides custom functions for common use cases.
randBase62
Section titled “randBase62”Generates a random string using base62 characters (0-9, A-Z, a-z). Useful for creating unique identifiers, passwords, or tokens.
Syntax:
{{ randBase62 <length> }}Parameters:
length(integer): The number of characters to generate
Example:
spec: helm: values: - raw: # Generate a 16-character random API key apiKey: "{{ randBase62 16 }}"
# Generate a 32-character random token token: "{{ randBase62 32 }}"
# Generate a short random suffix instanceId: "app-{{ randBase62 8 }}"Output examples:
apiKey: "aB3dE5fG7hJ9kL2m"token: "xY1zA2bC3dE4fG5hI6jK7lM8nO9pQ0rS"instanceId: "app-xY7zA2bC"Note: Each time the template is rendered, a new random value is generated. If you need consistent values across updates, use configuration values instead of randBase62.
Type Preservation
Section titled “Type Preservation”The rendering engine automatically preserves types:
# TemplatereplicaCount: "{{.config.replicas}}" # String with templateenabled: "{{.config.enableFeature}}" # String with template
# After rendering (if replicas=3, enableFeature=true)replicaCount: 3 # Converted to integerenabled: true # Converted to booleanThis works because the renderer:
- Executes the template to get a string result
- Attempts to parse the result as JSON
- Uses the parsed type if successful, otherwise keeps as string
Rendering Examples
Section titled “Rendering Examples”Helm Module with Full Templating
Section titled “Helm Module with Full Templating”apiVersion: batch.forkspacer.com/v1kind: Modulemetadata: name: postgresql namespace: default
config: - name: "Environment" alias: "env" option: default: "development" values: ["development", "staging", "production"]
- name: "Storage Size" alias: "storageSize" string: default: "10Gi" regex: "^[0-9]+(Mi|Gi|Ti)$"
- name: "Replicas" alias: "replicas" integer: default: 1 min: 1 max: 5
spec: helm: chart: repo: url: https://charts.bitnami.com/bitnami chart: postgresql # Template in version version: "{{ if eq .config.env \"production\" }}14.0.0{{ else }}13.0.0{{ end }}"
# Templated namespace namespace: "{{.config.env}}-database"
values: - raw: # Templates with type preservation replication: enabled: "{{ if gt .config.replicas 1 }}true{{ else }}false{{ end }}" readReplicas: "{{ sub .config.replicas 1 }}"
persistence: size: "{{.config.storageSize}}"
# Using releaseName fullnameOverride: "{{.releaseName}}-db"
outputs: - name: "Database Host" # Template in output value value: "{{.releaseName}}-postgresql.{{.namespace}}.svc.cluster.local"
workspace: name: dev-environment
config: env: "production" storageSize: "50Gi" replicas: 3After rendering, the Helm spec becomes:
helm: chart: repo: url: https://charts.bitnami.com/bitnami chart: postgresql version: "14.0.0" # Conditional evaluated
namespace: "production-database" # Template rendered
values: - raw: replication: enabled: true # Type preserved as boolean readReplicas: 2 # Type preserved as integer persistence: size: "50Gi" fullnameOverride: "default-a1b2c3d4e5f-db" # Using auto-generated releaseName
outputs: - name: "Database Host" value: "default-a1b2c3d4e5f-postgresql.production-database.svc.cluster.local" # Using auto-generated releaseNameCustom Module with Templating
Section titled “Custom Module with Templating”apiVersion: batch.forkspacer.com/v1kind: Modulemetadata: name: app-installer namespace: default
config: - name: "Application Version" alias: "version" string: default: "v1.0.0"
- name: "Debug Mode" alias: "debug" boolean: default: false
spec: custom: # Templated image tag image: "my-registry/installer:{{.config.version}}"
permissions: - workspace
workspace: name: dev-environment
config: version: "v2.1.0" debug: trueAfter rendering:
custom: image: "my-registry/installer:v2.1.0" permissions: - workspaceNamespace Rendering in Helm Modules
Section titled “Namespace Rendering in Helm Modules”The namespace field has special rendering behavior:
- First Pass: Renders namespace with
releaseNameandconfig - Second Pass: Renders the rest of the spec with
releaseName,config, and the renderednamespace
This allows namespace to be templated and then used in other template expressions:
spec: helm: namespace: "{{.config.env}}-apps"
values: - raw: ingress: # Can use the rendered namespace value host: "app.{{.namespace}}.example.com"Effective Namespace and Release Name
Section titled “Effective Namespace and Release Name”When working with Helm modules, especially with adopted releases, Forkspacer uses helper methods to determine the effective namespace and release name.
GetNamespace() Method
Section titled “GetNamespace() Method”When existingRelease is specified, the effective namespace is determined by GetNamespace():
- If
existingReleaseis set: returnsexistingRelease.namespace - Otherwise: returns
helm.namespace
This ensures proper namespace handling for adopted Helm releases.
GetReleaseName() Method
Section titled “GetReleaseName() Method”The effective release name is determined by GetReleaseName():
- If
existingReleaseis set: returnsexistingRelease.name(for adopted releases) - Otherwise: returns
helm.releaseName(either custom or auto-generated)
This ensures that templates always have access to the correct release name through .releaseName, regardless of whether the release is newly created or adopted.
Best Practices for Templating
Section titled “Best Practices for Templating”- Always quote template expressions: Use
"{{.config.value}}"to ensure valid YAML - Use type-aware templates: The renderer preserves types, so
"{{.config.replicas}}"becomes an integer - Validate early: Configuration validation happens before rendering, catching errors early
- Use meaningful defaults: Provide sensible defaults in config schema
- Document templates: Add comments explaining complex template logic
- Test with different configs: Verify templates work with various configuration values
- Avoid nested quotes: Template output shouldn’t contain quotes if you’re already quoting the template
Relationship with Workspace
Section titled “Relationship with Workspace”- A Module must reference an existing Workspace via the
workspacefield - Multiple Modules can be deployed to the same Workspace
- When a Workspace is hibernated, all its Modules may be affected
- If a Workspace is deleted, the operator’s behavior for associated Modules depends on finalization logic
Related Resources
Section titled “Related Resources”- Workspace CRD - Workspace resource reference