Generate helm docs

This commit is contained in:
Tom Proctor 2023-04-19 20:43:49 +01:00
parent a5d803ad3c
commit 8f237e2b82
No known key found for this signature in database
GPG key ID: 9AA1838744D16345
10 changed files with 1616 additions and 216 deletions

View file

@ -99,3 +99,11 @@ delete-kind:
kind delete cluster --name ${KIND_CLUSTER_NAME} || :
.PHONY: values-schema test-image test-unit test-bats test test-acceptance test-destroy test-provision acceptance provision-cluster destroy-cluster
# Generate Helm reference docs from values.yaml and update Vault website.
# Usage: make gen-helm-docs vault=<path-to-vault-repo>.
# If no options are given, the local copy of docs/helm.mdx will be updated, which can
# be used to submit a PR to vault docs.
# Adapted from https://github.com/hashicorp/consul-k8s/tree/main/hack/helm-reference-gen
gen-helm-docs:
@cd hack/helm-reference-gen; go run ./... --vault=$(vault)

View file

@ -0,0 +1,199 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package main
import (
"errors"
"fmt"
"strings"
)
const UnknownKindError = "unknown kind"
// DocNode is a node in the final generated reference document.
// For example this would be a single DocNode:
// ```
// - `global` ((#v-global)) - Holds values that affect multiple components of the chart.
// ```
type DocNode struct {
// Column is the character column (i.e. indent) this node should be displayed
// at.
// For example, if this is a root node, then its column will be 0 because it
// shouldn't be indented.
Column int
// ParentBreadcrumb is the path to this node's parent from the root.
// It is used for the HTML anchor, e.g. `#v-global-name`.
// If this node were global.name, then this would be set to "global".
ParentBreadcrumb string
// ParentWasMap is true when the parent of this node was a map.
ParentWasMap bool
// Key is the key of this node, e.g. if `key: value` then Key would be "key".
Key string
// Default is the default value for this node, e.g. if key defaults to false,
// Default would be "false".
Default string
// Comment is the YAML comment that described this node.
Comment string
// KindTag is the YAML parsed kind tag from the YAML library. This has values
// like "!!seq" and "!!str".
KindTag string
// Children are other nodes that should be displayed as sub-keys of this node.
Children []DocNode
}
// Validate returns an error if this node is invalid, else nil.
func (n DocNode) Validate() error {
kind := n.FormattedKind()
if strings.Contains(kind, UnknownKindError) {
return errors.New(kind)
}
return nil
}
// HTMLAnchor constructs the HTML anchor to be used to link to this node.
func (n DocNode) HTMLAnchor() string {
return fmt.Sprintf("%s-%s", n.ParentBreadcrumb, strings.ToLower(n.Key))
}
// FormattedDefault returns the default value for this node formatted properly.
func (n DocNode) FormattedDefault() string {
// Check for the annotation first.
if match := defaultAnnotation.FindAllStringSubmatch(n.Comment, -1); len(match) > 0 {
// Handle it being set > 1 time. Use the last match.
return match[len(match)-1][1]
}
// We don't show the default if the kind is a map of arrays or map because the
// default will be too big to show inline.
if n.FormattedKind() == "array<map>" || n.FormattedKind() == "map" {
return ""
}
if n.Default != "" && n.Default != "null" {
// Don't show multiline string defaults since it wouldn't fit.
// We use > 2 because if it's extraConfig, e.g. `{}` then we want to
// show it but if it's affinity then it doesn't make sense to show it.
if len(strings.Split(n.Default, "\n")) > 2 {
return ""
}
if n.FormattedKind() == "string" {
return fmt.Sprintf("\"%s\"", strings.TrimSpace(n.Default))
}
return strings.TrimSpace(n.Default)
}
// If we get here then the default is an empty string. We return quotes
// in this case so it's clear it's an empty string. Otherwise it would look
// like: `string: ` vs. `string: ""`.
return `""`
}
// FormattedDocumentation returns the formatted documentation for this node.
func (n DocNode) FormattedDocumentation() string {
doc := n.Comment
// Replace all leading YAML comment characters, e.g.
// `# yaml comment` => `yaml comment`.
doc = commentPrefix.ReplaceAllString(n.Comment, "")
doc = strings.ReplaceAll(doc, "https://developer.hashicorp.com/vault/docs", "/vault/docs")
// Indent each line of the documentation so it lines up correctly.
var indentedLines []string
var inCodeBlock bool
for i, line := range strings.Split(doc, "\n") {
if strings.HasPrefix(line, "```") {
inCodeBlock = !inCodeBlock
}
// If the line is a @type, @default or @recurse annotation we don't include it in
// the markdown description.
// This check must be before the i == 0 check because if there's only
// one line in the description and it's the type description then we
// want to discard it.
if len(typeAnnotation.FindStringSubmatch(line)) > 0 ||
len(defaultAnnotation.FindStringSubmatch(line)) > 0 ||
len(recurseAnnotation.FindStringSubmatch(line)) > 0 {
continue
}
var indentedLine string
// The first line is printed inline with the key information so it
// doesn't need to be indented, e.g.
// `key - first line docs`
if i == 0 {
indentedLine = line
} else if line != "" {
if !inCodeBlock && !strings.HasPrefix(line, "```") {
indentedLines[len(indentedLines)-1] += " " + line
continue
}
indent := n.Column + 1
if n.ParentWasMap {
indent = n.Column
}
indentedLine = strings.Repeat(" ", indent) + line
} else {
// No need to add whitespace indent to a newline.
}
indentedLines = append(indentedLines, indentedLine)
}
// Trim all final newlines and whitespace.
return strings.TrimRight(strings.Join(indentedLines, "\n"), "\n ")
}
// FormattedKind returns the kind of this node, e.g. string, boolean, etc.
func (n DocNode) FormattedKind() string {
// Check for the annotation first.
if match := typeAnnotation.FindAllStringSubmatch(n.Comment, -1); len(match) > 0 {
// Handle it being set > 1 time. Use the last match.
return match[len(match)-1][1]
}
// Special case for secretName, secretKey so they don't need to set
// # type: string.
if n.Key == "secretName" || n.Key == "secretKey" {
return "string"
}
// The YAML kind tag looks like "!!str".
switch strings.TrimLeft(n.KindTag, "!") {
case "str":
return "string"
case "int":
return "int"
case "bool":
return "boolean"
case "map":
// We don't show the kind if its of type because it's obvious it's a map
// because it will have subkeys and so showing the type as map would
// just complicate reading without any benefit.
// NOTE: If it's been explicitly annotated with @type: map then we
// will show it as that is handled above via the typeAnnotation regex
// match.
return ""
case "seq":
return "array"
case "null":
return ""
default:
return fmt.Sprintf("%s '%v'", UnknownKindError, n.KindTag)
}
}
// LeadingIndent returns the leading indentation for the first line of this
// node.
func (n DocNode) LeadingIndent() string {
indent := n.Column - 1
if n.ParentWasMap {
indent = n.Column - 3
}
return strings.Repeat(" ", indent)
}

View file

@ -0,0 +1,178 @@
## Top-Level Stanzas
Use these links to navigate to a particular top-level stanza.
- [`controller`](#h-controller)
- [`metricsService`](#h-metricsservice)
- [`defaultVaultConnection`](#h-defaultvaultconnection)
- [`defaultAuthMethod`](#h-defaultauthmethod)
- [`tests`](#h-tests)
## All Values
### controller ((#h-controller))
- `controller` ((#v-controller)) - Top level configuration for the vault secrets operator deployment.
This is comprised of a controller and a kube rbac proxy container.
- `replicas` ((#v-controller-replicas)) (`integer: 1`) - Set the number of replicas for the operator.
- `kubeRbacProxy` ((#v-controller-kuberbacproxy)) - Settings related to the kubeRbacProxy container. This container is an HTTP proxy for the
controller manager which performs RBAC authorization against the Kubernetes API using SubjectAccessReviews.
- `image` ((#v-controller-kuberbacproxy-image)) - Image sets the repo and tag of the kube-rbac-proxy image to use for the controller.
- `repository` ((#v-controller-kuberbacproxy-image-repository)) (`string: gcr.io/kubebuilder/kube-rbac-proxy`)
- `tag` ((#v-controller-kuberbacproxy-image-tag)) (`string: v0.11.0`)
- `resources` ((#v-controller-kuberbacproxy-resources)) (`map`) - Configures the default resources for the kube rbac proxy container.
For more information on configuring resources, see the K8s documentation:
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
- `limits` ((#v-controller-kuberbacproxy-resources-limits))
- `cpu` ((#v-controller-kuberbacproxy-resources-limits-cpu)) (`string: 500m`)
- `memory` ((#v-controller-kuberbacproxy-resources-limits-memory)) (`string: 128Mi`)
- `requests` ((#v-controller-kuberbacproxy-resources-requests))
- `cpu` ((#v-controller-kuberbacproxy-resources-requests-cpu)) (`string: 5m`)
- `memory` ((#v-controller-kuberbacproxy-resources-requests-memory)) (`string: 64Mi`)
- `manager` ((#v-controller-manager)) - Settings related to the vault-secrets-operator container.
- `image` ((#v-controller-manager-image)) - Image sets the repo and tag of the vault-secrets-operator image to use for the controller.
- `repository` ((#v-controller-manager-image-repository)) (`string: hashicorp/vault-secrets-operator`)
- `tag` ((#v-controller-manager-image-tag)) (`string: 0.0.0-dev`)
- `resources` ((#v-controller-manager-resources)) (`map`) - Configures the default resources for the vault-secrets-operator container.
For more information on configuring resources, see the K8s documentation:
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
- `limits` ((#v-controller-manager-resources-limits))
- `cpu` ((#v-controller-manager-resources-limits-cpu)) (`string: 500m`)
- `memory` ((#v-controller-manager-resources-limits-memory)) (`string: 128Mi`)
- `requests` ((#v-controller-manager-resources-requests))
- `cpu` ((#v-controller-manager-resources-requests-cpu)) (`string: 10m`)
- `memory` ((#v-controller-manager-resources-requests-memory)) (`string: 64Mi`)
- `controllerConfigMapYaml` ((#v-controller-controllerconfigmapyaml)) (`map`) - Sets the configuration settings used by the controller. Any custom changes will be reflected in the
data field of the configmap.
For more information on configuring resources, see the K8s documentation:
https://kubernetes.io/docs/concepts/configuration/configmap/
- `health` ((#v-controller-controllerconfigmapyaml-health))
- `healthProbeBindAddress` ((#v-controller-controllerconfigmapyaml-health-healthprobebindaddress)) (`string: :8081`)
- `leaderElection` ((#v-controller-controllerconfigmapyaml-leaderelection))
- `leaderElect` ((#v-controller-controllerconfigmapyaml-leaderelection-leaderelect)) (`boolean: true`)
- `resourceName` ((#v-controller-controllerconfigmapyaml-leaderelection-resourcename)) (`string: b0d477c0.hashicorp.com`)
- `metrics` ((#v-controller-controllerconfigmapyaml-metrics))
- `bindAddress` ((#v-controller-controllerconfigmapyaml-metrics-bindaddress)) (`string: 127.0.0.1:8080`)
- `webhook` ((#v-controller-controllerconfigmapyaml-webhook))
- `port` ((#v-controller-controllerconfigmapyaml-webhook-port)) (`integer: 9443`)
- `kubernetesClusterDomain` ((#v-controller-kubernetesclusterdomain)) (`string: cluster.local`) - Configures the environment variable KUBERNETES_CLUSTER_DOMAIN used by KubeDNS.
### metricsService ((#h-metricsservice))
- `metricsService` ((#v-metricsservice)) (`map`) - Configure the metrics service ports used by the metrics service.
Set the configuration fo the metricsService port.
- `ports` ((#v-metricsservice-ports)) (`map`) - Set the port settings for the metrics service.
For more information on configuring resources, see the K8s documentation:
https://kubernetes.io/docs/concepts/services-networking/service/
- `name` ((#v-metricsservice-ports-name)) (`string: https`)
- `port` ((#v-metricsservice-ports-port)) (`integer: 8443`)
- `protocol` ((#v-metricsservice-ports-protocol)) (`string: TCP`)
- `targetPort` ((#v-metricsservice-ports-targetport)) (`string: https`)
- `type` ((#v-metricsservice-type)) (`string: ClusterIP`)
### defaultVaultConnection ((#h-defaultvaultconnection))
- `defaultVaultConnection` ((#v-defaultvaultconnection)) - Configures the default VaultConnection CR which will be used by resources
if they do not specify a VaultConnection reference. The name is 'default' and will
always be installed in the same namespace as the operator.
- `enabled` ((#v-defaultvaultconnection-enabled)) (`boolean: false`) - toggles the deployment of the VaultAuthMethod CR
- `address` ((#v-defaultvaultconnection-address)) (`string: http://vault.default.svc.cluster.local:8200`) - Address of the Vault Server
- `caCertSecret` ((#v-defaultvaultconnection-cacertsecret)) (`string: ""`) - CACertSecret containing the trusted PEM encoded CA certificate chain.
Note: This secret must exist prior to deploying the CR.
- `tlsServerName` ((#v-defaultvaultconnection-tlsservername)) (`string: ""`) - TLSServerName to use as the SNI host for TLS connections.
- `skipTLSVerify` ((#v-defaultvaultconnection-skiptlsverify)) (`boolean: false`) - SkipTLSVerify for TLS connections.
- `headers` ((#v-defaultvaultconnection-headers)) (`string: ""`) - Headers to be included in all Vault requests.
headers: |
"vault-something1": "foo"
"vault-something2": "bar"
"vault-something3": "baz"
### defaultAuthMethod ((#h-defaultauthmethod))
- `defaultAuthMethod` ((#v-defaultauthmethod)) - Configures and deploys the default VaultAuthMethod CR which will be used by resources
if they do not specify a VaultAuthMethod reference. The name is 'default' and will
always be installed in the same namespace as the operator.
- `enabled` ((#v-defaultauthmethod-enabled)) (`boolean: false`) - toggles the deployment of the VaultAuthMethod CR
- `namespace` ((#v-defaultauthmethod-namespace)) (`string: default`) - Vault namespace for the VaultAuthMethod CR
- `method` ((#v-defaultauthmethod-method)) (`string: kubernetes`) - Vault Auth method to be used with the VaultAuthMethod CR
- `mount` ((#v-defaultauthmethod-mount)) (`string: kubernetes`) - Mount path for the Vault Auth Method.
- `kubernetes` ((#v-defaultauthmethod-kubernetes)) - Vault Kubernetes auth method specific configuration
- `role` ((#v-defaultauthmethod-kubernetes-role)) (`string: demo`) - Vault Auth Role to use
This is a required field and must be setup in Vault prior to deploying the helm chart
if `defaultAuthMethod.enabled=true`
TODO: mark required in the charts.
- `serviceAccount` ((#v-defaultauthmethod-kubernetes-serviceaccount)) (`string: default`) - Kubernetes ServiceAccount associated with the default Vault Auth Role
- `tokenAudiences` ((#v-defaultauthmethod-kubernetes-tokenaudiences)) (`array<string>: []`) - Token Audience is required and should match whatever the audience
of the vault kubernetes auth role has set.
- `params` ((#v-defaultauthmethod-params)) (`string: ""`) - Params to use when authenticating to Vault
params: |
"vault-something1": "foo"
"vault-something2": "bar"
"vault-something3": "baz"
- `headers` ((#v-defaultauthmethod-headers)) (`string: ""`) - Headers to be included in all Vault requests.
headers: |
"vault-something1": "foo"
"vault-something2": "bar"
"vault-something3": "baz"
### tests ((#h-tests))
- `tests` ((#v-tests)) - # Used by unit tests, and will not be rendered except when using `helm template`, this can be safely ignored.
- `enabled` ((#v-tests-enabled)) (`boolean: true`)

View file

@ -0,0 +1,183 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0
# Top level configuration for the vault secrets operator deployment.
# This is comprised of a controller and a kube rbac proxy container.
controller:
# Set the number of replicas for the operator.
# @type: integer
replicas: 1
# Settings related to the kubeRbacProxy container. This container is an HTTP proxy for the
# controller manager which performs RBAC authorization against the Kubernetes API using SubjectAccessReviews.
kubeRbacProxy:
# Image sets the repo and tag of the kube-rbac-proxy image to use for the controller.
image:
repository: gcr.io/kubebuilder/kube-rbac-proxy
tag: v0.11.0
# Configures the default resources for the kube rbac proxy container.
# For more information on configuring resources, see the K8s documentation:
# https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
# @recurse: true
# @type: map
resources:
limits:
cpu: 500m
memory: 128Mi
requests:
cpu: 5m
memory: 64Mi
# Settings related to the vault-secrets-operator container.
manager:
# Image sets the repo and tag of the vault-secrets-operator image to use for the controller.
image:
repository: hashicorp/vault-secrets-operator
tag: 0.0.0-dev
# Configures the default resources for the vault-secrets-operator container.
# For more information on configuring resources, see the K8s documentation:
# https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
# @recurse: true
# @type: map
resources:
limits:
cpu: 500m
memory: 128Mi
requests:
cpu: 10m
memory: 64Mi
# Sets the configuration settings used by the controller. Any custom changes will be reflected in the
# data field of the configmap.
# For more information on configuring resources, see the K8s documentation:
# https://kubernetes.io/docs/concepts/configuration/configmap/
# @recurse: true
# @type: map
controllerConfigMapYaml:
health:
healthProbeBindAddress: :8081
leaderElection:
leaderElect: true
resourceName: b0d477c0.hashicorp.com
metrics:
bindAddress: 127.0.0.1:8080
webhook:
port: 9443
# Configures the environment variable KUBERNETES_CLUSTER_DOMAIN used by KubeDNS.
# @type: string
kubernetesClusterDomain: cluster.local
# Configure the metrics service ports used by the metrics service.
# Set the configuration fo the metricsService port.
# @recurse: true
# @type: map
metricsService:
# Set the port settings for the metrics service.
# For more information on configuring resources, see the K8s documentation:
# https://kubernetes.io/docs/concepts/services-networking/service/
# @type: map
ports:
- name: https
port: 8443
protocol: TCP
targetPort: https
type: ClusterIP
# Configures the default VaultConnection CR which will be used by resources
# if they do not specify a VaultConnection reference. The name is 'default' and will
# always be installed in the same namespace as the operator.
defaultVaultConnection:
# toggles the deployment of the VaultAuthMethod CR
# @type: boolean
enabled: false
# Address of the Vault Server
# @type: string
address: http://vault.default.svc.cluster.local:8200
# CACertSecret containing the trusted PEM encoded CA certificate chain.
# Note: This secret must exist prior to deploying the CR.
# @type: string
caCertSecret: ""
# TLSServerName to use as the SNI host for TLS connections.
# @type: string
tlsServerName: ""
# SkipTLSVerify for TLS connections.
# @type: boolean
skipTLSVerify: false
# Headers to be included in all Vault requests.
# @type: string, eg:
# headers: |
# "vault-something1": "foo"
# "vault-something2": "bar"
# "vault-something3": "baz"
# @type: string
headers: ""
# Configures and deploys the default VaultAuthMethod CR which will be used by resources
# if they do not specify a VaultAuthMethod reference. The name is 'default' and will
# always be installed in the same namespace as the operator.
defaultAuthMethod:
# toggles the deployment of the VaultAuthMethod CR
# @type: boolean
enabled: false
# Vault namespace for the VaultAuthMethod CR
# @type: string
namespace: default
# Vault Auth method to be used with the VaultAuthMethod CR
# @type: string
method: kubernetes
# Mount path for the Vault Auth Method.
# @type: string
mount: kubernetes
# Vault Kubernetes auth method specific configuration
kubernetes:
# Vault Auth Role to use
# This is a required field and must be setup in Vault prior to deploying the helm chart
# if `defaultAuthMethod.enabled=true`
# TODO: mark required in the charts.
# @type: string
role: demo
# Kubernetes ServiceAccount associated with the default Vault Auth Role
# @type: string
serviceAccount: default
# Token Audience is required and should match whatever the audience
# of the vault kubernetes auth role has set.
# @type: array<string>
tokenAudiences: []
# Params to use when authenticating to Vault
# params: |
# "vault-something1": "foo"
# "vault-something2": "bar"
# "vault-something3": "baz"
# @type: string
params: ""
# Headers to be included in all Vault requests.
# headers: |
# "vault-something1": "foo"
# "vault-something2": "bar"
# "vault-something3": "baz"
# @type: string
headers: ""
## Used by unit tests, and will not be rendered except when using `helm template`, this can be safely ignored.
tests:
# @type: boolean
enabled: true

View file

@ -0,0 +1,13 @@
module github.com/hashicorp/consul-k8s/hack/helm-reference-gen
go 1.19
require (
github.com/stretchr/testify v1.6.1
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
)

View file

@ -0,0 +1,12 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -0,0 +1,425 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package main
// This script generates markdown documentation out of the values.yaml file
// for use on vault.io.
//
// Usage: make gen-helm-docs [vault-repo-path] [-validate]
// Where [vault-repo-path] is the location of the hashicorp/vault repo. Defaults to ../../../vault.
// If -validate is set, the generated docs won't be output anywhere.
// This is useful in CI to ensure the generation will succeed.
import (
"bytes"
"flag"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"text/template"
"gopkg.in/yaml.v3"
)
const (
tocPrefix = "## Top-Level Stanzas\n\nUse these links to navigate to a particular top-level stanza.\n\n"
tocSuffix = "\n## All Values"
)
var (
// typeAnnotation matches the @type annotation. It captures the value of @type.
typeAnnotation = regexp.MustCompile(`(?m).*@type: (.*)$`)
// defaultAnnotation matches the @default annotation. It captures the value of @default.
defaultAnnotation = regexp.MustCompile(`(?m).*@default: (.*)$`)
// recurseAnnotation matches the @recurse annotation. It captures the value of @recurse.
recurseAnnotation = regexp.MustCompile(`(?m).*@recurse: (.*)$`)
// commentPrefix matches on the YAML comment prefix, e.g.
// ```
// # comment here
// # comment with indent
// ```
// Will match on "comment here" and "comment with indent".
//
// It also properly handles YAML comments inside code fences, e.g.
// ```
// # Example:
// # ```yaml
// # # yaml comment
// # ````
// ```
// And will not match the "# yaml comment" incorrectly.
commentPrefix = regexp.MustCompile(`(?m)^[^\S\n]*#[^\S\n]?`)
funcMap = template.FuncMap{
"ToLower": strings.ToLower,
}
// docNodeTmpl is the go template used to print a DocNode node.
// We use $ instead of ` in the template so we can use the golang raw string
// format. We then do the replace from $ => `.
docNodeTmpl = template.Must(
template.New("").Funcs(funcMap).Parse(
strings.Replace(
`{{- if eq .Column 1 }}## {{ .Key }}
{{ end }}{{ .LeadingIndent }}- ${{ .Key }}${{ if ne .FormattedKind "" }} (${{ .FormattedKind }}{{ if .FormattedDefault }}: {{ .FormattedDefault }}{{ end }}$){{ end }}{{ if .FormattedDocumentation}} - {{ .FormattedDocumentation }}{{ end }}`,
"$", "`", -1)),
)
)
func main() {
validateFlag := flag.Bool("validate", false, "only validate that the markdown can be generated, don't actually generate anything")
vaultMdxFlag := flag.String("vault", "", "path to the helm reference documentation file")
chartDocsPath := "../../"
flag.Parse()
if *vaultMdxFlag == "" {
*vaultMdxFlag = "docs/helm.mdx"
}
if len(os.Args) > 3 {
fmt.Println("Error: extra arguments")
os.Exit(1)
}
if !*validateFlag {
// Only argument is path to Vault repo. If not set then we default.
if len(os.Args) < 2 {
abs, _ := filepath.Abs(chartDocsPath)
fmt.Printf("Defaulting to Vault repo path: %s\n", abs)
} else {
// Support absolute and relative paths to the Vault repo.
if filepath.IsAbs(os.Args[1]) {
chartDocsPath = os.Args[1]
} else {
chartDocsPath = filepath.Join("../..", *vaultMdxFlag)
}
abs, _ := filepath.Abs(chartDocsPath)
fmt.Printf("Using Vault repo path: %s\n", abs)
}
}
// Parse the values.yaml file.
inputBytes, err := os.ReadFile("../../values.yaml")
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
out, err := GenerateDocs(string(inputBytes))
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
// If we're just validating that generation will succeed then we're done.
if *validateFlag {
fmt.Println("Validation successful")
os.Exit(0)
}
// Otherwise we'll go on to write the changes to the helm docs.
helmReferenceFile := filepath.Join(chartDocsPath)
helmReferenceBytes, err := os.ReadFile(helmReferenceFile)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
helmReferenceContents := string(helmReferenceBytes)
// Swap out the contents between the codegen markers.
startStr := "<!-- codegen: start -->\n\n"
endStr := "\n<!-- codegen: end -->"
start := strings.Index(helmReferenceContents, startStr)
if start == -1 {
fmt.Printf("%q not found in %q\n", startStr, helmReferenceFile)
os.Exit(1)
}
end := strings.Index(helmReferenceContents, endStr)
if end == -1 {
fmt.Printf("%q not found in %q\n", endStr, helmReferenceFile)
os.Exit(1)
}
newMdx := helmReferenceContents[0:start+len(startStr)] + out + helmReferenceContents[end:]
err = os.WriteFile(helmReferenceFile, []byte(newMdx), 0o644)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
abs, _ := filepath.Abs(helmReferenceFile)
fmt.Printf("Updated with generated docs: %s\n", abs)
}
func GenerateDocs(yamlStr string) (string, error) {
node, err := Parse(yamlStr)
if err != nil {
return "", fmt.Errorf("failed to parse values.yaml: %w", err)
}
children, err := generateDocsFromNode(docNodeTmpl, node)
if err != nil {
return "", err
}
// enterpriseSubst := strings.ReplaceAll(strings.Join(children, "\n\n"), "[Enterprise Only]", "<EnterpriseAlert inline />")
// // Add table of contents.
// toc := generateTOC(node)
return strings.Join(children, "\n\n") + "\n\n", nil
}
// Parse parses yamlStr into a tree of DocNode's.
func Parse(yamlStr string) (DocNode, error) {
var node yaml.Node
err := yaml.Unmarshal([]byte(yamlStr), &node)
if err != nil {
return DocNode{}, err
}
// Due to how the YAML is parsed this is the first real node.
rootNode := node.Content[0].Content
children, err := parseNodeContent(rootNode, "", false)
if err != nil {
return DocNode{}, err
}
return DocNode{
Column: 0,
Children: children,
}, nil
}
// parseNodeContent recursively parses the yaml nodes and outputs a DocNode
// tree.
func parseNodeContent(nodeContent []*yaml.Node, parentBreadcrumb string, parentWasMap bool) ([]DocNode, error) {
var docNodes []DocNode
// This is a special type of node where it's an array of maps.
// e.g.
// ````
// ingressGateways:
// - name: name
// ````
//
// In this case we show the docs as:
// - ingress-gateway: ingress gateway descrip
// - name: name descrip.
//
// To do that, we actually need to skip the map node.
if len(nodeContent) == 1 {
return parseNodeContent(nodeContent[0].Content, parentBreadcrumb, true)
}
// skipNext is true if we should skip the next node. Due to how the YAML is
// parsed, a key: value pair results in two YAML nodes but we only need
// doc node out of that so in the loop we look ahead to the next node
// and use it to construct our DocNode. Then we can skip it on the next
// iteration.
skipNext := false
for i, child := range nodeContent {
if skipNext {
skipNext = false
continue
}
docNode, err := buildDocNode(i, child, nodeContent, parentBreadcrumb, parentWasMap)
if err != nil {
return nil, err
}
if err := docNode.Validate(); err != nil {
return nil, &ParseError{
FullAnchor: docNode.HTMLAnchor(),
Err: err.Error(),
}
}
docNodes = append(docNodes, docNode)
skipNext = true
continue
}
return docNodes, nil
}
func generateDocsFromNode(tm *template.Template, node DocNode) ([]string, error) {
var out []string
for _, child := range node.Children {
var nodeOut bytes.Buffer
err := tm.Execute(&nodeOut, child)
if err != nil {
return nil, err
}
childOut, err := generateDocsFromNode(tm, child)
if err != nil {
return nil, err
}
out = append(append(out, nodeOut.String()), childOut...)
}
return out, nil
}
// allScalars returns true if content contains only scalar nodes
// with no chidren.
func allScalars(content []*yaml.Node) bool {
for _, n := range content {
if n.Kind != yaml.ScalarNode || len(n.Content) > 0 {
return false
}
}
return true
}
// toInlineYaml will return the yaml string representation for content
// using the inline representation, i.e. `["a", "b"]`
// instead of:
// ```
// - "a"
// - "b"
// ```
func toInlineYaml(content []*yaml.Node) (string, error) {
// We have to use this struct so we can set the struct tag "flow" so the
// generated yaml uses the inline format.
type intermediary struct {
Arr []*yaml.Node `yaml:"arr,flow"`
}
i := intermediary{
Arr: content,
}
out, err := yaml.Marshal(i)
if err != nil {
return "", err
}
// Hack: because we had to use our struct, it has the key "arr: " which
// we need to trim. Before trimming it will look like:
// `arr: ["a","b"]`.
return strings.TrimPrefix(string(out), "arr: "), nil
}
func buildDocNode(nodeContentIdx int, currNode *yaml.Node, nodeContent []*yaml.Node, parentBreadcrumb string, parentWasMap bool) (DocNode, error) {
// Check for the @recurse: false annotation.
// In this case we construct our node and then don't recurse further.
if match := recurseAnnotation.FindStringSubmatch(currNode.HeadComment); len(match) > 0 && match[1] == "false" {
return DocNode{
Column: currNode.Column,
ParentBreadcrumb: parentBreadcrumb,
ParentWasMap: false,
Key: currNode.Value,
Comment: currNode.HeadComment,
}, nil
}
// Nodes should come in pairs.
if len(nodeContent) < nodeContentIdx+1 {
return DocNode{}, &ParseError{
ParentAnchor: parentBreadcrumb,
CurrAnchor: currNode.Value,
Err: fmt.Sprintf("content length incorrect, expected %d got %d", nodeContentIdx+1, len(nodeContent)),
}
}
next := nodeContent[nodeContentIdx+1]
switch next.Kind {
// If it's a scalar then this is a simple key: value node.
case yaml.ScalarNode:
return DocNode{
ParentBreadcrumb: parentBreadcrumb,
ParentWasMap: parentWasMap,
Column: currNode.Column,
Key: currNode.Value,
Comment: currNode.HeadComment,
KindTag: next.Tag,
Default: next.Value,
}, nil
// If it's a map then we will need to recurse into it.
case yaml.MappingNode:
docNode := DocNode{
ParentBreadcrumb: parentBreadcrumb,
ParentWasMap: parentWasMap,
Column: currNode.Column,
Key: currNode.Value,
Comment: currNode.HeadComment,
KindTag: next.Tag,
}
var err error
docNode.Children, err = parseNodeContent(next.Content, docNode.HTMLAnchor(), false)
if err != nil {
return DocNode{}, err
}
return docNode, nil
// If it's a sequence, i.e. array, then we have to handle it differently
// depending on its contents.
case yaml.SequenceNode:
// If it's empty then its just a key with a default of empty array.
if len(next.Content) == 0 {
return DocNode{
ParentBreadcrumb: parentBreadcrumb,
ParentWasMap: parentWasMap,
Column: currNode.Column,
Key: currNode.Value,
// Default is empty array.
Default: "[]",
Comment: currNode.HeadComment,
KindTag: next.Tag,
}, nil
// If it's full of scalars, e.g. key: [a, b] then we can stop recursing
// and use the value as the default.
} else if allScalars(next.Content) {
inlineYaml, err := toInlineYaml(next.Content)
if err != nil {
return DocNode{}, &ParseError{
ParentAnchor: parentBreadcrumb,
CurrAnchor: currNode.Value,
Err: err.Error(),
}
}
return DocNode{
ParentBreadcrumb: parentBreadcrumb,
ParentWasMap: parentWasMap,
Column: currNode.Column,
Key: currNode.Value,
// Default will be the yaml value.
Default: inlineYaml,
Comment: currNode.HeadComment,
KindTag: next.Tag,
}, nil
} else {
// Otherwise we need to recurse into each element of the array.
docNode := DocNode{
ParentBreadcrumb: parentBreadcrumb,
ParentWasMap: parentWasMap,
Column: currNode.Column,
Key: currNode.Value,
Comment: currNode.HeadComment,
KindTag: next.Tag,
}
var err error
docNode.Children, err = parseNodeContent(next.Content, docNode.HTMLAnchor(), false)
if err != nil {
return DocNode{}, err
}
return docNode, nil
}
}
return DocNode{}, fmt.Errorf("fell through cases unexpectedly at breadcrumb: %s", parentBreadcrumb)
}
func generateTOC(node DocNode) string {
toc := tocPrefix
for _, c := range node.Children {
toc += fmt.Sprintf("- [`%s`](#h-%s)\n", c.Key, strings.ToLower(c.Key))
}
return toc + tocSuffix
}

View file

@ -0,0 +1,190 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package main
import (
"os"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
// Test various smaller cases and special cases.
func Test(t *testing.T) {
cases := map[string]struct {
Input string
Exp string
}{
"string value": {
Input: `---
# Line 1
# Line 2
key: value`,
Exp: `- [$key$](#h-key)
## All Values
### key ((#h-key))
- $key$ ((#v-key)) ($string: value$) - Line 1\n Line 2
`,
},
"integer value": {
Input: `---
# Line 1
# Line 2
replicas: 3`,
Exp: `- [$replicas$](#h-replicas)
## All Values
### replicas ((#h-replicas))
- $replicas$ ((#v-replicas)) ($integer: 3$) - Line 1\n Line 2
`,
},
"boolean value": {
Input: `---
# Line 1
# Line 2
enabled: true`,
Exp: `- [$enabled$](#h-enabled)
## All Values
### enabled ((#h-enabled))
- $enabled$ ((#v-enabled)) ($boolean: true$) - Line 1\n Line 2
`,
},
"map": {
Input: `---
# Map line 1
# Map line 2
map:
# Key line 1
# Key line 2
key: value`,
Exp: `- [$map$](#h-map)
## All Values
### map ((#h-map))
- $map$ ((#v-map)) - Map line 1\n Map line 2
- $key$ ((#v-map-key)) ($string: value$) - Key line 1\n Key line 2
`,
},
"map with multiple keys": {
Input: `---
# Map line 1
# Map line 2
map:
# Key line 1
# Key line 2
key: value
# Int docs
int: 1
# Bool docs
bool: true`,
Exp: `- [$map$](#h-map)
## All Values
### map ((#h-map))
- $map$ ((#v-map)) - Map line 1\n Map line 2
- $key$ ((#v-map-key)) ($string: value$) - Key line 1
Key line 2
- $int$ ((#v-map-int)) ($integer: 1$) - Int docs
- $bool$ ((#v-map-bool)) ($boolean: true$) - Bool docs
`,
},
"null value": {
Input: `---
# key docs
# @type: string
key: null`,
Exp: `- [$key$](#h-key)
## All Values
### key ((#h-key))
- $key$ ((#v-key)) ($string: null$) - key docs
`,
},
"description with empty line": {
Input: `---
# line 1
#
# line 2
key: value`,
Exp: `- [$key$](#h-key)
## All Values
### key ((#h-key))
- $key$ ((#v-key)) ($string: value$) - line 1\n\n line 2
`,
},
"array of strings": {
Input: `---
# line 1
# @type: array<string>
serverAdditionalDNSSANs: []
`,
Exp: `- [$serverAdditionalDNSSANs$](#h-serveradditionaldnssans)
## All Values
### serverAdditionalDNSSANs ((#h-serveradditionaldnssans))
- $serverAdditionalDNSSANs$ ((#v-serveradditionaldnssans)) ($array<string>: []$) - line 1
`,
},
}
for name, c := range cases {
t.Run(name, func(t *testing.T) {
// Swap $ for `.
input := strings.Replace(c.Input, "$", "`", -1)
out, err := GenerateDocs(input)
require.NoError(t, err)
// Swap $ for `.
exp := strings.Replace(c.Exp, "$", "`", -1)
// Swap \n for real \n.
exp = strings.Replace(exp, "\\n", "\n", -1)
exp = tocPrefix + exp
require.Equal(t, exp, out)
})
}
}
// Test against a full values file and compare against a golden file.
func TestFullValues(t *testing.T) {
inputBytes, err := os.ReadFile(filepath.Join("fixtures", "full-values.yaml"))
require.NoError(t, err)
expBytes, err := os.ReadFile(filepath.Join("fixtures", "full-values.golden"))
require.NoError(t, err)
actual, err := GenerateDocs(string(inputBytes))
require.NoError(t, err)
if actual != string(expBytes) {
require.NoError(t, os.WriteFile(filepath.Join("fixtures", "full-values.actual"), []byte(actual), 0o644))
require.FailNow(t, "output not equal, actual output to full-values.actual")
}
}

View file

@ -0,0 +1,23 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package main
import "fmt"
// ParseError is an error that occurs during parsing.
// It's used to include information about which node failed to parse.
type ParseError struct {
ParentAnchor string
CurrAnchor string
FullAnchor string
Err string
}
func (p *ParseError) Error() string {
anchor := p.FullAnchor
if anchor == "" {
anchor = fmt.Sprintf("%s-%s", p.ParentAnchor, p.CurrAnchor)
}
return fmt.Sprintf("%s: %s", anchor, p.Err)
}

View file

@ -3,187 +3,260 @@
# Available parameters and their default values for the Vault chart.
# These global values affect multiple components of the chart.
global:
# enabled is the master enabled switch. Setting this to true or false
# will enable or disable all the components within this chart by default.
# The global enabled/disabled configuration. If this is true, most components
# will be installed by default. If this is false, no components will be
# installed by default and manually opting-in is required, such as by setting
# `server.enabled` to true.
enabled: true
# Image pull secret to use for registry authentication.
# Alternatively, the value may be specified as an array of strings.
imagePullSecrets: []
# References secrets to be used when pulling images from private registries.
# See [Pull an Image from a Private Registry](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/)
# for more details. May be specified as an array of name map entries or just
# as an array of names:
#
# ```yaml
# imagePullSecrets:
# - name: image-pull-secret
# # or
# imagePullSecrets:
# - image-pull-secret
# ```
imagePullSecrets: []
# TLS for end-to-end encrypted transport
# When set to `true`, changes URLs from `https` to `http` (such as the
# `VAULT_ADDR=http://127.0.0.1:8200` environment variable set on the
# Vault pods).
tlsDisable: true
# External vault server address for the injector and CSI provider to use.
# Setting this will disable deployment of a vault server.
# Setting this will disable deployment of a vault server. A service account
# with token review permissions is automatically created if
# `server.serviceAccount.create=true` is set for the external Vault server
# to use.
externalVaultAddr: ""
# If deploying to OpenShift
# If `true`, enables configuration specific to OpenShift such as NetworkPolicy,
# SecurityContext, and Route.
openshift: false
# Create PodSecurityPolicy for pods
# Values that configure Pod Security Policy.
psp:
# When set to `true`, enables Pod Security Policies for Vault and Vault Agent Injector.
enable: false
# Annotation for PodSecurityPolicy.
# This is a multi-line templated string map, and can also be set as YAML.
# This value defines additional annotations to add to the Pod Security
# Policies. This can either be YAML or a YAML-formatted multi-line templated
# string.
#
# ```yaml
# annotations:
# seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default,runtime/default
# apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
# seccomp.security.alpha.kubernetes.io/defaultProfileName: runtime/default
# apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
# # or
# annotations: |
# seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default,runtime/default
# apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
# seccomp.security.alpha.kubernetes.io/defaultProfileName: runtime/default
# apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
# ```
annotations: |
seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default,runtime/default
apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
seccomp.security.alpha.kubernetes.io/defaultProfileName: runtime/default
apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
# Values that configure metrics and telemetry.
serverTelemetry:
# Enable integration with the Prometheus Operator
# See the top level serverTelemetry section below before enabling this feature.
# When set to `true`, enables integration with the Prometheus Operator. Be
# sure to configure the top-level [`serverTelemetry`](https://developer.hashicorp.com/vault/docs/platform/k8s/helm/configuration#servertelemetry-1)
# section for more details and required configuration values.
prometheusOperator: false
# Values that configure running a Vault Agent Injector Admission Webhook
# Controller within Kubernetes.
injector:
# True if you want to enable vault agent injection.
# @default: global.enabled
# When set to `true`, the Vault Agent Injector Admission Webhook controller
# will be created. When set to `"-"`, defaults to the value of `global.enabled`.
# @type: boolean or string
enabled: "-"
replicas: 1
# Configures the port the injector should listen on
port: 8080
# If multiple replicas are specified, by default a leader will be determined
# so that only one injector attempts to create TLS certificates.
leaderElector:
enabled: true
# If true, will enable a node exporter metrics endpoint at /metrics.
metrics:
enabled: false
# Deprecated: Please use global.externalVaultAddr instead.
# Deprecated: Please use [global.externalVaultAddr](https://developer.hashicorp.com/vault/docs/platform/k8s/helm/configuration#externalvaultaddr)
# instead.
externalVaultAddr: ""
# image sets the repo and tag of the vault-k8s image to use for the injector.
# The number of pods to deploy to create a highly available cluster of Vault
# Agent Injectors. Requires Vault K8s 0.7.0 to have more than 1 replica.
replicas: 1
# Values that configure the Vault Agent Injector leader election for HA
# deployments.
leaderElector:
# When set to `true`, enables leader election for Vault Agent Injector. This
# is required when using auto-tls and more than 1 replica.
enabled: true
# Values that configure the Vault Agent Injector Docker image.
image:
# The name of the Docker image for Vault Agent Injector.
repository: "hashicorp/vault-k8s"
# The tag of the Docker image for the Vault Agent Injector. **This should
# be pinned to a specific version when running in production.** Otherwise,
# other changes to the chart may inadvertently upgrade your admission controller.
tag: "1.2.1"
# The pull policy for container images. The default pull policy is `IfNotPresent`
# which causes the Kubelet to skip pulling an image if it already exists.
pullPolicy: IfNotPresent
# agentImage sets the repo and tag of the Vault image to use for the Vault Agent
# containers. This should be set to the official Vault image. Vault 1.3.1+ is
# required.
# Values that configure the Vault Agent sidecar image.
agentImage:
# The name of the Docker image for the Vault Agent sidecar. This should be
# set to the official Vault Docker image.
repository: "hashicorp/vault"
# The tag of the Vault Docker image to use for the Vault Agent Sidecar.
# **Vault 1.3.1+ is required by the admission controller**.
tag: "1.13.1"
# The default values for the injected Vault Agent containers.
# Values that configure the injected Vault Agent containers default values.
# For more information on configuring resources, see the Kubernetes documentation:
# https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
agentDefaults:
# For more information on configuring resources, see the K8s documentation:
# https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
# The default CPU limit for injected Vault Agent containers.
cpuLimit: "500m"
# The default CPU request for injected Vault Agent containers.
cpuRequest: "250m"
# The default memory limit for injected Vault Agent containers.
memLimit: "128Mi"
# The default memory request for injected Vault Agent containers.
memRequest: "64Mi"
# Default template type for secrets when no custom template is specified.
# Possible values include: "json" and "map".
# The default template type for rendered secrets if no custom templates are
# defined. Possible values include `map` and `json`.
template: "map"
# Default values within Agent's template_config stanza.
# Default values within Agent's [`template_config` stanza](https://developer.hashicorp.com/vault/docs/agent/template).
templateConfig:
# Controls whether Vault Agent exits after it has exhausted its number of
# template retry attempts due to failures.
exitOnRetryFailure: true
# Configures how often Vault Agent Template should render non-leased secrets
# such as KV v2. See the [Vault Agent Templates documentation](/docs/agent/template#non-renewable-secrets)
# for more details.
staticSecretRenderInterval: ""
# Used to define custom livenessProbe settings
livenessProbe:
# When a probe fails, Kubernetes will try failureThreshold times before giving up
failureThreshold: 2
# Number of seconds after the container has started before probe initiates
initialDelaySeconds: 5
# How often (in seconds) to perform the probe
periodSeconds: 2
# Minimum consecutive successes for the probe to be considered successful after having failed
successThreshold: 1
# Number of seconds after which the probe times out.
timeoutSeconds: 5
# Used to define custom readinessProbe settings
readinessProbe:
# When a probe fails, Kubernetes will try failureThreshold times before giving up
failureThreshold: 2
# Number of seconds after the container has started before probe initiates
initialDelaySeconds: 5
# How often (in seconds) to perform the probe
periodSeconds: 2
# Minimum consecutive successes for the probe to be considered successful after having failed
successThreshold: 1
# Number of seconds after which the probe times out.
timeoutSeconds: 5
# Used to define custom startupProbe settings
startupProbe:
# When a probe fails, Kubernetes will try failureThreshold times before giving up
failureThreshold: 12
# Number of seconds after the container has started before probe initiates
initialDelaySeconds: 5
# How often (in seconds) to perform the probe
periodSeconds: 5
# Minimum consecutive successes for the probe to be considered successful after having failed
successThreshold: 1
# Number of seconds after which the probe times out.
timeoutSeconds: 5
# Values that configure the Vault Agent Injector metric exporter.
metrics:
# When set to `true`, the Vault Agent Injector exports Prometheus metrics at
# the `/metrics` path.
enabled: false
# Mount Path of the Vault Kubernetes Auth Method.
# Mount path of the Vault Kubernetes Auth Method.
authPath: "auth/kubernetes"
# Configures the log verbosity of the injector.
# Supported log levels include: trace, debug, info, warn, error
# Configures the log verbosity of the injector. Supported log levels: trace,
# debug, error, warn, info.
logLevel: "info"
# Configures the log format of the injector. Supported log formats: "standard", "json".
# Configures the log format of the injector. Supported log formats: "standard",
# "json".
logFormat: "standard"
# Configures all Vault Agent sidecars to revoke their token when shutting down
# Configures all Vault Agent sidecars to revoke their token when shutting down.
revokeOnShutdown: false
webhook:
# Configures failurePolicy of the webhook. The "unspecified" default behaviour depends on the
# API Version of the WebHook.
# To block pod creation while the webhook is unavailable, set the policy to `Fail` below.
# See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy
# Security context for the pod template and the injector container.
securityContext:
# Defines the securityContext for the injector Pod, as YAML or a YAML-formatted
# multi-line templated string. Default if not specified:
#
# ```yaml
# runAsNonRoot: true
# runAsGroup: {{ .Values.injector.gid | default 1000 }}
# runAsUser: {{ .Values.injector.uid | default 100 }}
# fsGroup: {{ .Values.injector.gid | default 1000 }}
# ```
# @type: dictionary
# @default: {}
pod: {}
# Defines the securityContext for the injector container, as YAML or a
# YAML-formatted multi-line templated string. Default if not specified:
#
# ```yaml
# allowPrivilegeEscalation: false
# capabilities:
# drop:
# - ALL
# ```
# @type: dictionary
# @default: {}
container: {}
# The resource requests and limits (CPU, memory, etc.) for each container of
# the injector. This should be a YAML dictionary of a Kubernetes
# [ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#resourcerequirements-v1-core)
# object. If this isn't specified, then the pods won't request any specific
# amount of resources, which limits the ability for Kubernetes to make
# efficient use of compute resources.
#
# **Setting this is highly recommended.**
#
# ```yaml
# resources:
# requests:
# memory: '256Mi'
# cpu: '250m'
# limits:
# memory: '256Mi'
# cpu: '250m'
# ```
# @type: dictionary
# @default: {}
resources: {}
# Values that control the Mutating Webhook Configuration.
webhook:
# Configures failurePolicy of the webhook. To block pod creation while the
# webhook is unavailable, set the policy to `"Fail"`. See
# [Failure Policy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy).
failurePolicy: Ignore
# matchPolicy specifies the approach to accepting changes based on the rules of
# the MutatingWebhookConfiguration.
# See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy
# for more details.
#
# Specifies the approach to accepting changes based on the rules of the
# MutatingWebhookConfiguration. See
# [Match Policy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy).
matchPolicy: Exact
# timeoutSeconds is the amount of seconds before the webhook request will be ignored
# or fails.
# If it is ignored or fails depends on the failurePolicy
# See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#timeouts
# for more details.
#
# Specifies the number of seconds before the webhook request will be ignored
# or fails. If it is ignored or fails depends on the `failurePolicy`. See
# [timeouts](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#timeouts).
timeoutSeconds: 30
# namespaceSelector is the selector for restricting the webhook to only
# specific namespaces.
# See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector
# for more details.
# Example:
# The selector used by the admission webhook controller to limit what
# namespaces where injection can happen. If unset, all non-system namespaces
# are eligible for injection. See
# [Matching requests: namespace selector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector).
#
# ```yaml
# namespaceSelector:
# matchLabels:
# sidecar-injector: enabled
# matchLabels:
# sidecar-injector: enabled
# ```
# @type: object
# @default: {}
namespaceSelector: {}
# objectSelector is the selector for restricting the webhook to only
# specific labels.
# See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector
# for more details.
# Example:
# The selector used by the admission webhook controller to limit what objects
# can be affected by mutation. See
# [Matching requests: object selector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector).
#
# ```yaml
# objectSelector:
# matchLabels:
# vault-sidecar-injector: enabled
# matchLabels:
# sidecar-injector: enabled
# ```
# @type: object
# @default: {}
objectSelector: |
matchExpressions:
- key: app.kubernetes.io/name
@ -191,95 +264,91 @@ injector:
values:
- {{ template "vault.name" . }}-agent-injector
# Extra annotations to attach to the webhook
# Defines additional annotations to attach to the webhook. This can either be
# YAML or a YAML-formatted multi-line templated string.
# @type: string or object
# @default: {}
annotations: {}
# Deprecated: please use 'webhook.failurePolicy' instead
# Configures failurePolicy of the webhook. The "unspecified" default behaviour depends on the
# API Version of the WebHook.
# To block pod creation while webhook is unavailable, set the policy to `Fail` below.
# See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy
#
failurePolicy: Ignore
# Deprecated: please use 'webhook.namespaceSelector' instead
# namespaceSelector is the selector for restricting the webhook to only
# specific namespaces.
# See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector
# for more details.
# Example:
# namespaceSelector:
# matchLabels:
# sidecar-injector: enabled
# Deprecated: please use
# [`webhook.namespaceSelector`](https://developer.hashicorp.com/vault/docs/platform/k8s/helm/configuration#namespaceselector) instead.
# @type: dictionary
# @default: {}
namespaceSelector: {}
# Deprecated: please use 'webhook.objectSelector' instead
# objectSelector is the selector for restricting the webhook to only
# specific labels.
# See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector
# for more details.
# Example:
# objectSelector:
# matchLabels:
# vault-sidecar-injector: enabled
# Deprecated: please use
# [`webhook.objectSelector`](https://developer.hashicorp.com/vault/docs/platform/k8s/helm/configuration#objectselector) instead.
# @type: dictionary
# @default: {}
objectSelector: {}
# Deprecated: please use 'webhook.annotations' instead
# Extra annotations to attach to the webhook
webhookAnnotations: {}
# This value defines additional labels for Vault Agent Injector pods.
#
# ```yaml
# extraLabels:
# 'sample/label1': 'foo'
# 'sample/label2': 'bar'
# ```
# @type: dictionary
# @default: {}
extraLabels: {}
# The certs section configures how the webhook TLS certs are configured. These
# are the TLS certs for the Kube apiserver communicating to the webhook. By
# default, the injector will generate and manage its own certs, but this
# requires the ability for the injector to update its own
# `MutatingWebhookConfiguration`. In a production environment, custom certs
# should probably be used. Configure the values below to enable this.
certs:
# secretName is the name of the secret that has the TLS certificate and
# private key to serve the injector webhook. If this is null, then the
# injector will default to its automatic management mode that will assign
# a service account to the injector to generate its own certificates.
# secretName is the name of the Kubernetes secret that has the TLS certificate
# and private key to serve the injector webhook. If this is null, then the
# injector will default to its automatic management mode.
secretName: null
# caBundle is a base64-encoded PEM-encoded certificate bundle for the CA
# that signed the TLS certificate that the webhook serves. This must be set
# if secretName is non-null unless an external service like cert-manager is
# keeping the caBundle updated.
# The PEM-encoded CA public certificate bundle for the TLS certificate served
# by the injector. This must be specified as a string and can't come from a
# secret because it must be statically configured on the Kubernetes
# `MutatingAdmissionWebhook` resource. This only needs to be specified if
# `secretName` is not null.
caBundle: ""
# certName and keyName are the names of the files within the secret for
# the TLS cert and private key, respectively. These have reasonable
# defaults but can be customized if necessary.
# The name of the certificate file within the `secretName` secret.
certName: tls.crt
# The name of the key file within the `secretName` secret.
keyName: tls.key
# Security context for the pod template and the injector container
# The default pod securityContext is:
# runAsNonRoot: true
# runAsGroup: {{ .Values.injector.gid | default 1000 }}
# runAsUser: {{ .Values.injector.uid | default 100 }}
# fsGroup: {{ .Values.injector.gid | default 1000 }}
# and for container is
# allowPrivilegeEscalation: false
# capabilities:
# drop:
# - ALL
securityContext:
pod: {}
container: {}
resources: {}
# resources:
# requests:
# memory: 256Mi
# cpu: 250m
# limits:
# memory: 256Mi
# cpu: 250m
# extraEnvironmentVars is a list of extra environment variables to set in the
# injector deployment.
# Extra environment variables to set in the injector deployment.
#
# ```yaml
# # Example setting injector TLS options in a deployment:
# extraEnvironmentVars:
# AGENT_INJECT_TLS_MIN_VERSION: tls13
# AGENT_INJECT_TLS_CIPHER_SUITES: ...
# ```
# @type: dictionary
# @default: {}
extraEnvironmentVars: {}
# KUBERNETES_SERVICE_HOST: kubernetes.default.svc
# Affinity Settings for injector pods
# This can either be a multi-line string or YAML matching the PodSpec's affinity field.
# Commenting out or setting as empty the affinity variable, will allow
# deployment of multiple replicas to single node services such as Minikube.
# This value defines the [affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity)
# for Vault Agent Injector pods. This can either be multi-line string or YAML
# matching the PodSpec's affinity field. It defaults to allowing only a single
# pod on each node, which minimizes risk of the cluster becoming unusable if
# a node is lost. If you need to run more pods per node (for example, testing
# on Minikube), set this value to `null`.
#
# ```yaml
# # Recommended default server affinity:
# affinity: |
# podAntiAffinity:
# requiredDuringSchedulingIgnoredDuringExecution:
# - labelSelector:
# matchLabels:
# app.kubernetes.io/name: {{ template "vault.name" . }}-agent-injector
# app.kubernetes.io/instance: "{{ .Release.Name }}"
# component: webhook
# topologyKey: kubernetes.io/hostname
# ```
# @type: string or dictionary
affinity: |
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
@ -290,64 +359,164 @@ injector:
component: webhook
topologyKey: kubernetes.io/hostname
# Topology settings for injector pods
# ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
# This should be either a multi-line string or YAML matching the topologySpreadConstraints array
# in a PodSpec.
# [Topology settings](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/)
# for injector pods. This can either be YAML or a YAML-formatted multi-line
# templated string.
topologySpreadConstraints: []
# Toleration Settings for injector pods
# This should be either a multi-line string or YAML matching the Toleration array
# in a PodSpec.
# Toleration Settings for injector pods. This should be either a multi-line
# string or YAML matching the Toleration array.
tolerations: []
# nodeSelector labels for server pod assignment, formatted as a multi-line string or YAML map.
# ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
# Example:
# The nodeSelector labels for injector pod assignment, formatted as a multi-line
# string or YAML map. See https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
#
# ```yaml
# nodeSelector:
# beta.kubernetes.io/arch: amd64
# ```
# @type: dictionary
# @default: {}
nodeSelector: {}
# Priority class for injector pods
# Priority class for injector pods.
priorityClassName: ""
# Extra annotations to attach to the injector pods
# This can either be YAML or a YAML-formatted multi-line templated string map
# of the annotations to apply to the injector pods
# This value defines additional annotations for injector pods. This can either
# be YAML or a YAML-formatted multi-line templated string.
#
# ```yaml
# annotations:
# "sample/annotation1": "foo"
# "sample/annotation2": "bar"
# # or
# annotations: |
# "sample/annotation1": "foo"
# "sample/annotation2": "bar"
# ```
# @type: dictionary
# @default: {}
annotations: {}
# Extra labels to attach to the agent-injector
# This should be a YAML map of the labels to apply to the injector
extraLabels: {}
# Deprecated: please use [`webhook.failurePolicy`](https://developer.hashicorp.com/vault/docs/platform/k8s/helm/configuration#failurepolicy) instead.
failurePolicy: Ignore
# Should the injector pods run on the host network (useful when using
# an alternate CNI in EKS)
# Deprecated: please use [`webhook.annotations`](https://developer.hashicorp.com/vault/docs/platform/k8s/helm/configuration#annotations-1) instead.
# @type: dictionary
# @default: {}
webhookAnnotations: {}
# The service section configures the Kubernetes service for the Vault Agent
# Injector.
service:
# This value defines additional annotations to add to the Vault Agent Injector
# service. This can either be YAML or a YAML-formatted multi-line templated string.
#
# ```yaml
# annotations:
# "sample/annotation1": "foo"
# "sample/annotation2": "bar"
# # or
# annotations: |
# "sample/annotation1": "foo"
# "sample/annotation2": "bar"
# ```
# @type: dictionary
# @default: {}
annotations: {}
# Injector serviceAccount specific config.
serviceAccount:
# Extra annotations to attach to the injector serviceAccount. This can either
# be YAML or a YAML-formatted multi-line templated string.
# @type: dictionary
# @default: {}
annotations: {}
# When set to true, configures the Vault Agent Injector to run on the host
# network. This is useful when alternative cluster networking is used.
hostNetwork: false
# Injector service specific config
service:
# Extra annotations to attach to the injector service
annotations: {}
# Injector serviceAccount specific config
serviceAccount:
# Extra annotations to attach to the injector serviceAccount
annotations: {}
# Configures the port the Vault Agent Injector listens on.
port: 8080
# A disruption budget limits the number of pods of a replicated application
# that are down simultaneously from voluntary disruptions
podDisruptionBudget: {}
# that are down simultaneously from voluntary disruptions.
#
# ```yaml
# podDisruptionBudget:
# maxUnavailable: 1
# ```
# @type: dictionary
# @default: {}
podDisruptionBudget: {}
# strategy for updating the deployment. This can be a multi-line string or a
# Strategy for updating the deployment. This can be a multi-line string or a
# YAML map.
strategy: {}
#
# ```yaml
# strategy:
# rollingUpdate:
# maxSurge: 25%
# maxUnavailable: 25%
# type: RollingUpdate
# # or
# strategy: |
# rollingUpdate:
# maxSurge: 25%
# maxUnavailable: 25%
# type: RollingUpdate
# ```
# @type: dictionary
# @default: {}
strategy: {}
# Values that configure the liveness probe for the injector.
livenessProbe:
# When set to a value, configures how many probe failures will be tolerated
# by Kubernetes.
failureThreshold: 2
# Sets the initial delay of the liveness probe when the container starts.
initialDelaySeconds: 5
# When set to a value, configures how often (in seconds) to perform the probe.
periodSeconds: 2
# When set to a value, configures the minimum consecutive successes for the
# probe to be considered successful after having failed.
successThreshold: 1
# When set to a value, configures the number of seconds after which the probe
# times out.
timeoutSeconds: 5
# Values that configure the readiness probe for the injector.
readinessProbe:
# When set to a value, configures how many probe failures will be tolerated
# by Kubernetes.
failureThreshold: 2
# Sets the initial delay of the readiness probe when the container starts.
initialDelaySeconds: 5
# When set to a value, configures how often (in seconds) to perform the probe.
periodSeconds: 2
# When set to a value, configures the minimum consecutive successes for the probe
# to be considered successful after having failed.
successThreshold: 1
# When set to a value, configures the number of seconds after which the probe
# times out.
timeoutSeconds: 5
# Values that configure the startup probe for the injector.
startupProbe:
# When set to a value, configures how many probe failures will be tolerated
# by Kubernetes.
failureThreshold: 12
# Sets the initial delay of the startup probe when the container starts.
initialDelaySeconds: 5
# When set to a value, configures how often (in seconds) to perform the probe.
periodSeconds: 5
# When set to a value, configures the minimum consecutive successes for the probe
# to be considered successful after having failed.
successThreshold: 1
# When set to a value, configures the number of seconds after which the probe
# times out.
timeoutSeconds: 5
server:
# If true, or "-" with global.enabled true, Vault server will be installed.