CtrlK
BlogDocsLog inGet started
Tessl Logo

nic-add-feature

Checklists for adding Ingress annotations, VirtualServer/VSR fields, or Helm chart values to NIC. Use when adding new configuration options, new NGINX directives, new annotations, new CRD fields, or new Helm values.

74

Quality

91%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

Adding Features to NIC

Adding a New Annotation (Ingress Only)

Annotations apply ONLY to Ingress objects, never to VirtualServer or VirtualServerRoute.

  1. Add constant in internal/configs/annotations.go (e.g., MyAnnotation = "nginx.org/my-annotation")
  2. Add field to ConfigParams in internal/configs/config_params.go
  3. Parse it in parseAnnotations() in internal/configs/annotations.go
  4. Update masterDenylist / minionDenylist if it should not be on master/minion
  5. Apply it in generateNginxCfg() in internal/configs/ingress.go
  6. Add the NGINX directive in internal/configs/version1/nginx.ingress.tmpl and internal/configs/version1/nginx-plus.ingress.tmpl
  7. Add validation in internal/k8s/validation.go annotation validation chains
  8. Add tests in annotations_test.go and ingress_test.go

Gotchas

  • Never forget both OSS and Plus templates -- they are separate files
  • Use containsDangerousChars() for any user-provided string that ends up in NGINX config
  • parseAnnotations() silently ignores unknown annotations -- add the constant first

Adding a New VirtualServer/VSR Field

  1. Add field to the appropriate struct in pkg/apis/configuration/v1/types.go with kubebuilder markers
  2. Run make update-codegen and make update-crds
  3. Add validation in pkg/apis/configuration/validation/virtualserver.go
  4. Add to the version2 template struct in internal/configs/version2/http.go
  5. Wire in internal/configs/virtualserver.go (GenerateVirtualServerConfig or helper)
  6. Add template rendering in nginx.virtualserver.tmpl / nginx-plus.virtualserver.tmpl
  7. Update snapshot tests and run make test-update-snaps

JSON Tag Conventions

  • NGINX-proxy-related fields: kebab-case (json:"lb-method", json:"fail-timeout")
  • K8s/application fields: camelCase (json:"ingressClassName", json:"rewritePath")

Pointer vs Value Types

  • *int, *bool, *SomeStruct = optional/nullable
  • Plain int, bool = required or zero-value default
  • Booleans defaulting to false must be non-pointer

Kubebuilder Markers

MarkerPurpose
+kubebuilder:validation:RequiredField must be present
+kubebuilder:validation:OptionalField is optional
+kubebuilder:validation:Pattern= `regex`Regex validation
+kubebuilder:validation:Minimum=NNumeric minimum
+kubebuilder:validation:MinItems=N / MaxItems=NArray length
+kubebuilder:validation:MaxLength=NMax string length
+kubebuilder:default=valueDefault value
+kubebuilder:validation:XValidation:rule="CEL"Cross-field CEL validation

CEL Validation Examples

// Prevent wildcard origin with credentials
// +kubebuilder:validation:XValidation:rule="!(self.allowOrigin.exists(origin, origin == '*') && has(self.allowCredentials) && self.allowCredentials == true)",message="..."

// Require time when allowedCodes is set
// +kubebuilder:validation:XValidation:rule="!has(self.allowedCodes) || (has(self.allowedCodes) && has(self.time))",message="..."

Gotchas

  • Never skip make update-codegen after changing types.go
  • Never edit zz_generated.deepcopy.go manually
  • Version 2 has a single Server block; Version 1 has multiple Server blocks

Adding a Helm Chart Value

  1. Add to charts/nginx-ingress/values.yaml with ## documentation above the field
  2. Add JSON schema in charts/nginx-ingress/values.schema.json
  3. If it maps to a CLI arg: add to nginx-ingress.args in charts/nginx-ingress/templates/_helpers.tpl
  4. If it maps to a ConfigMap key: add to charts/nginx-ingress/templates/controller-configmap.yaml
  5. If it needs volumes/mounts: add to the volume helpers in _helpers.tpl
  6. Create a testdata file in charts/tests/testdata/<feature>.yaml
  7. Add test case in charts/tests/helmunit_test.go
  8. Run make test-update-snaps to capture the new snapshot

Gotchas

  • Always update all three workload templates (deployment, daemonset, statefulset) when they share logic via helpers
  • Always update values.schema.json alongside values.yaml
  • Helm tests use terratest + go-snaps: charts/tests/helmunit_test.go
Repository
nginx/kubernetes-ingress
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.