TL;DR:
Platform features can be added or removed by adding or removing feature modules and their cluster bindings. The easiest way to do so is to ask your AI coding agent that has learned the Kubestack skill to scaffold the module for you.
Following the skill, your agent only makes changes to local files, and you can see the changes with git status.
To have the changes take effect, you have to commit, push, merge and promote them following the GitOps flow.
Adding a platform feature adds a module directory modules/<feature_name>/ and one binding file per cluster to your repository.
Ask your agent to scaffold the feature for you.
Your agent researches the upstream source, renders it using helm template for Helm charts or fetches the upstream manifest for plain YAML, and configures the provider and environments of the new feature to match the cluster it is added to automatically.
# add the nginx feature to all platform clustersAdd the nginx platform feature to all clusters
# or optionally only add a feature to a single clusterAdd the nginx platform feature to the eks_gc0_eu-west-1 clusterYou can also ask your agent to remove a platform feature for you.
# list all platform componentsgit ls-files '*_feature_*.tf'aks_gc0_westeurope_feature_nginx.tfeks_gc0_eu-west-1_feature_nginx.tfgke_gc0_europe-west1_feature_nginx.tf
# then ask your agent to remove the desired feature by <name>Remove the nginx platform feature from the gke_gc0_europe-west1 clusterPlatform feature modules call the framework's kustomization overlay module.
The overlay provides the same attributes available in a kustomization.yaml.
See the commenteded examples below for more details and how to use them inside Terraform syntax.
module "example" { providers = { kustomization = kustomization }
# kustomization overlay module, use the framework version # that all other modules in your repository use source = "github.com/kbst/terraform-kubestack//kustomization/overlay?ref=<version>"
configuration = { apps = { # list of paths to YAML files or Kustomizations to deploy # (required) resources = [ "${path.module}/manifests/upstream.yaml" ]
# set annotations on all Kubernetes resources # (optional), defaults to null common_annotations = { "example-annotation" = var.example_annotation }
# set labels on all Kubernetes resources # (optional), defaults to null common_labels = { "example-label" = var.example_label }
# generate Kubernetes configMaps # (optional), defaults to null config_map_generator = [{ # name (required) # Sets 'metadata.name' of the configMap resource name = "example"
# namespace (required) # Sets 'metadata.namespace' of the configMap resource namespace = "example"
# behavior (optional) # Valid values: 'create', 'replace' or 'merge'. Defaults to 'create'. behavior = "create"
# literals (optional) # List of 'KEY=VALUE' strings. Sets 'data[KEY] = VALUE' in the configMap. literals = [ "KEY=VALUE" ]
# envs (optional) # List of paths (strings) to env files (one KEY=VALUE pair per line). # Sets 'data[KEY] = VALUE' in the configMap per line in the env file. envs = [ "${path.module}/manifests/env" ]
# files (optional) # List of paths (strings) to files. # Sets 'data[KEY] = file_content'. KEY defaults to the file's name. # Overwrite by prefixing 'customkey='. files = [ "${path.module}/manifests/cfg.ini" # data["cfg.ini"] = file_content "prod.ini=${path.module}/manifests/cfg.ini" # data["prod.ini"] = file_content ]
# options (optional) # Same as top level 'generator_options' but specific to this configMap. options = { # see generator_options } }]
# generate Kubernetes secrets # (optional), defaults to null secret_generator = [{ # name (required) # Sets 'metadata.name' of the secret resource name = "example"
# namespace (required) # Sets 'metadata.namespace' of the secret resource namespace = "example"
# behavior (optional) # Valid values: 'create', 'replace' or 'merge'. Defaults to 'create'. behavior = "create"
# type (optional) # 'type' attribute of the secret to generate. type = "generic"
# literals (optional) # List of 'KEY=VALUE' strings. Sets 'data[KEY] = VALUE' in the secret. literals = [ "KEY=VALUE" ]
# envs (optional) # List of paths (strings) to env files (one KEY=VALUE pair per line). # Sets 'data[KEY] = VALUE' in the secret per line in the env file. envs = [ "${path.module}/manifests/env" ]
# files (optional) # List of paths (strings) to files. # Sets 'data[KEY] = file_content'. KEY defaults to the file's name. # Overwrite by prefixing 'customkey='. files = [ "${path.module}/manifests/cfg.ini" # data["cfg.ini"] = file_content "prod.ini=${path.module}/manifests/cfg.ini" # data["prod.ini"] = file_content ]
# options (optional) # Same as top level 'generator_options' but specific to this secret. options = { # see generator_options } }]
# set options for all configMap and secret generators # (optional), defaults to null generator_options = { # annotations (optional) # Sets 'metadata.annotations' on the generated resources. Defaults to '{}'. annotations = { example-annotation = "example" }
# labels (optional) # Sets 'metadata.labels' on the generated resources. Defaults to '{}'. labels = { example-label = "example" }
# disable_name_suffix_hash (optional) # Disables hash suffix of generated resource's 'metadata.name'. # Defaults to 'false'. disable_name_suffix_hash = true }
# patch image names, tags or digests # (optional), defaults to null images = [{ # Refers to the 'pod.spec.container.name' to modify the 'image' attribute of. name = "busybox"
# Customize the 'registry/name' part of the image. The part before the ':' new_name = "new_name"
# Customize the 'tag' part of the image. The part after the ':'. new_tag = "new_tag"
# Replace the 'tag' part of an image with a 'digest'. digest = "sha256:..." }]
# prefix or suffix to add to resource names # (optional), default to null name_prefix = "prefix-" name_suffix = "-suffix"
# namespace to set for all resources # (optional), default to null namespace = "example"
# patches to apply to resources # (optional), defaults to null patches = [{ # path (optional) # Path to a file that defines a strategic merge or JSON patch. path = "${path.module}/manifests/patch.yaml"
# patch (optional) # Inline string that defines a strategic merge or JSON patch. patch = <<-EOF - op: replace path: /metadata/name value: newname EOF
# target (optional) # Target one or multiple resources to be patched. target = { group = "" version = "v1" kind = "ConfigMap" name = "example" namespace = "example" label_selector = "key=value" annotation_selector = "key=value" } }]
# set replicas attribute of deployments and similar resources # (optional), defaults to null replicas = [{ # Refers to the 'metadata.name' of the resource to scale name = "example"
# Sets the desired number of replicas. count = 5 }] }
ops = {} }}
In addition to the convenience kustomization attributes documented above,
platform feature modules also pass the following low-level attributes through
to the kustomization provider.
These Kustomization attributes are less useful in the Terraform context and as such are not documented here.
components (optional) List of paths to Kustomize components.crds (optional) List of paths to Kustomize CRDs.generators (optional) List of paths to Kustomize generators.transformers (optional) List of paths to Kustomize transformers.vars (optional) List of objects to define Kustomize vars.