norwoodj / helm-docs Goto Github PK
View Code? Open in Web Editor NEWA tool for automatically generating markdown documentation for helm charts
License: GNU General Public License v3.0
A tool for automatically generating markdown documentation for helm charts
License: GNU General Public License v3.0
Just like templating of a group of charts can be done with one template, so can multiple groups of charts with similar templates. I would like to be able to either:
A. Be able to specify multiple template files and have them rendered in order or preferably
B. Be able to define templates at a global level that i can import in addition to the ones specified by the tool.
Thanks for helm-docs!
# comment 1
# -- key1
key1: {}
# comment 2
# -- key2
key2: {}
Key | Type | Default | Description |
---|---|---|---|
key1 | object | {} |
key1 |
key2 | object | {} |
key2 |
Key | Type | Default | Description |
---|---|---|---|
key1 | object | {} |
key1 |
key2 | object | {} |
Thanks for this great tool!
It would be awesome if it could merge it's content into an existing README w/o overwriting the contents - a bit similar to how terraform-docs works - by placing a placeholder in the original README:
<!--- BEGIN_TF_DOCS --->
it replaces the block with its generated contents.
Het @norwoodj. I saw you were having some personal issues via this comment and hope all is well. I would be more than happy to help maintain this repo and help clean up some of the legacy code/ci that exists (e.g. old cobra design and deprecated goreleaser config). I plan to use helm-docs for the ever growing k8s@home charts repo as well as a few other projects. If you would be more comfortable with me cloning the repo to preserve commits and starting in a new repository with attribution thats fine too!
Thanks!
I'm generating my README from README.md.gotmpl
I'm setting this inside the README.md.gotmpl
{{- .Values.container..resources | toYaml | nindent 4 }}
but, it's complaining with the following error
Error generating gotemplates for chart /helm: template: /helm:190: function "toYaml" not defined
When maintaining multiple charts in a single repository, it's inevitable that some charts require custom README templates.
Currently, this is possible using the --template-files
option: if a template is not found, a builtin default template is loaded.
This works flawlessly, until you want to pair it with an other use case: define a custom, common template for all the other charts. In other words: chart a should use the template README.md.gotmpl
, chart b and chart c should use ../../README.md.gotmpl
(template files are relative to chart directories).
Since chart b and chart c don't have README.md.gotmpl
, the builtin default template is loaded.
This issue can be worked around by symlinking the common template into every chart directory as needed, but that's not very elegant, is it? (You can see it working here though
One would think that passing both templates to the command would work (like this: --template-files ../../README.md.gotmpl --template-files README.md.gotmpl
). Passing the following would however result in the default template being loaded (see #77 for more details). Even after fixing #77, the result of this command will be a readme with the content rendered twice (more precisely: two similar readmes rendered in one file).
This is because internally, all templates are loaded into a single template instance and the entire template is rendered, resulting in an output containing the custom readme template and the builtin default as well.
A simple solution to this problem would be introducing a convention for loading a README.md.gotmpl
from the charts root directory as well. In this scenario, if no template files are defined, the default README.md.gotmpl
should be checked in the chart directory first, then one directory above.
This is far from perfect though: it doesn't solve more advanced use cases (ie. multiple template files)
A more elegant solution would be using named templates:
package main
import (
"os"
"text/template"
)
func main() {
// Load default template
tpl := template.Must(template.New("main").Parse("default template"))
// Define builtin templates
template.Must(tpl.Parse(`{{ define "header" }}header{{ end }}`))
// Load custom main templates
template.Must(tpl.New("main").Parse(`custom template: {{ template "header" .}}`))
// Load custom templates
tpl.ExecuteTemplate(os.Stdout, "main", nil)
}
(See it in action: https://play.golang.org/p/uizMUHwK4sF)
In this case, templates rendering the output and templates providing "blocks" are kept separate. There is always one main template (that renders the output), but there can be any number of additional template providing building blocks (eg. common header for all chart README templates, etc)
There is one pitfall: named templates are already used here, so we have to make sure they don't overlap.
In terms of implementation, we could introduce a new flag for main templates in addition to the existing --template-files
:
--main-template-files
--output-template-files
The new flag would work similarly to the solution outlined in #77: it would try to load all files, but instead of manually falling back to the default, the template system will take care of it for us, by each new template overriding the old one.
We can probably make this a backward compatible change: if no --main-template-files
are passed to the command, the old behavior is kept.
Alternatively, we can keep using a single flag and prepend main template file names with main:
: --template-files helpers.gotmpl --template-files main:../README.md.gotmpl --template-files main:README.md.gotmpl
. I find it less elegant, but resolves the ambiguity if having two template file flags doing different things.
All of the solutions above presume applying the same settings to each chart. Solution#2 relies on defining multiple templates, falling back in the list if one is not found.
A more direct approach to chart specific changes is chart specific configuration in the chart directory.
For example, a docs.yaml
:
templates:
- README.md.gotmpl
This would also need some sort of fallback though (eg. in the repo root).
Alternatively, we could use annotations in Chart.yaml
:
annotations:
helm-docs-templates: ../helpers.gotmpl;README.md.gotmpl
The above use case uncovers multiple problems:
Solution#2 provides a solution for the first problem without a need to solve the second one. It feels like it doesn't really need solving at the moment. We can always implement it later.
You can file this one under "Is this a feature or a bug?" Basically, when a special character like &
is present in an entry in values.yaml
, the rendered README.md
file shows the character as a Unicode sequence.
I encountered this because the elastic/elasticsearch charts allows specifying a value for clusterHealthCheckParams
, which I override in the following way:
elasticsearch:
# elasticsearch.clusterHealthCheckParams -- The Elasticsearch cluster health status params that will be used by readinessProbe command
clusterHealthCheckParams: "wait_for_status=yellow&timeout=1s"
This results in the following output README.md
file:
## Chart Values
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| elasticsearch.clusterHealthCheckParams | string | `"wait_for_status=yellow\u0026timeout=1s"` | The Elasticsearch cluster health status params that will be used by readinessProbe command |
Special characters such as &
should not be rendered as a Unicode sequence, and should show up as normal in the README.md
file as well.
A character like &
will get rendered as \u0026
.
Hi
thanks a lot for this great project.
i have a strange issue with a custom gotemplate within a subdir.
When i run helm-doc cli manually i got the exspected result:
❯ helm-docs --chart-search-root=. --template-files=README.md.gotmpl --template-files=./templates/_templates.gotpl -l debug
DEBU[2021-03-23T17:44:25+01:00] No ignore file found at helm-charts/.helmdocsignore, using empty ignore rules
INFO[2021-03-23T17:44:25+01:00] Found Chart directories [.]
DEBU[2021-03-23T17:44:25+01:00] Rendering from optional template files [README.md.gotmpl, templates/_templates.gotpl]
INFO[2021-03-23T17:44:25+01:00] Generating README Documentation for chart helm-charts/example
DEBU[2021-03-23T17:44:25+01:00] Using template files [README.md.gotmpl templates/_templates.gotpl] for chart helm-charts/example
but when i run exactly the same via pre-commit hook the template within the subdir was not found
❯ pre-commit run
Helm Docs................................................................Failed
- hook id: helm-docs
- files were modified by this hook
DEBU[2021-03-23T17:44:30+01:00] No ignore file found at helm-charts/.helmdocsignore, using empty ignore rules
DEBU[2021-03-23T17:44:30+01:00] Ignoring directory helm-charts/.git
INFO[2021-03-23T17:44:30+01:00] Found Chart directories [example]
DEBU[2021-03-23T17:44:30+01:00] Rendering from optional template files [README.md.gotmpl, ./templates/_templates.gotpl]
INFO[2021-03-23T17:44:30+01:00] Generating README Documentation for chart helm-charts/example
DEBU[2021-03-23T17:44:30+01:00] Did not find template file ./templates/_templates.gotpl for chart helm-charts/example, using default template
when i move the _templates.gotpl
under the chart root everything is working as expected.
Let's consider this snippet:
znapzend:
# znapzend.args -- List of command arguments
args:
- znapzend
- --logto=/dev/stdout
- --autoCreation
# znapzend.backupPlans -- List of backup plans to create/ensure on startup, see
# [values.yaml](./values.yaml) for an example
backupPlans: []
# - dataset: pool/dataset
## znapzend.backupPlans[].plan -- A backup plan object
# plan:
# selfResetAfter: 5m # Only effective when `metrics.enabled=true`, optional, default `1h`
# delaySeconds: 600 # Optional, default `0`
# source:
# retention: 1days=>2hours,2weeks=>1days,6months=>1weeks
# recursive: false # Optional, default `false`
# targets:
# - host: target.host
# dataset: backup/dataset
# retention: 1days=>2hours,2weeks=>1days,6months=>1weeks
Here, the backupPlans[]
is empty, as there isn't a sensible default possible because it's dependent on the user's setup. If they don't like it, it's impossible to disable this with Helm's merging behaviour unless the users provide their own list. Hence the empty array.
However, it would still be cool to have the objects in the array documented in the README, as it's kind of inconvenient to have them look in the values.yaml file (see znapzend.backupPlans[].plan
).
It's going to be difficult to implement, as the default YAML parsers ignore comments. But maybe we can add a @type
to the value similar to @default
done in #29, within double hashtag comments, e.g.
# znapzend.backupPlans -- List of backup plans to create/ensure on startup, see
# [values.yaml](./values.yaml) for an example
backupPlans: []
## znapzend.backupPlans[].dataset -- Source dataset path
## @type -- string
## @default -- ""
# - dataset: pool/dataset
## znapzend.backupPlans[].plan -- A backup plan object
## @type object
# plan: {} etc
@default
, e.g. @default -- ""
becomes string
if not specified by @type
?## key -- description
and ## @default -- ""
and so on would be enough for me.At the moment the generated README is just
| znapzend.backupPlans | list | `[]` | List of backup plans to create/ensure on startup, see [values.yaml](./values.yaml) for an example |
which ignores the documented example in values.yaml
completely
There are a few fields I don't want to show up in my README. Is there a way to explicitly ignore or exclude a field?
Can I generate documentation of subfields in object property whose default value is empty {}
?
worker:
deployment: {}
# expected format of `worker.deployment` is below:
# replicaCount: 1
# resources:
# cpu: "200m"
# memory: "512Mi"
In the example above, generated result was below:
Key | Type | Default | Description |
---|---|---|---|
worker.deployment | object | {} |
However, we wanna generate the documentation below:
Key | Type | Default | Description |
---|---|---|---|
worker.deployment | object | {} |
|
worker.deployment.replicaCount | int | ||
worker.deployment.resources.cpu | string | ||
worker.deployment.resources.memory | string |
My suggestion is introduction of the annotation (ex. @subfield
) which allows us for documentation of subfield.
worker:
# worker.deployment -- deployment of worker.
# @subfield replicaCount -- (int) replicaCount of worker.
# @subfield resources.cpu -- (string) cpu resources of worker.
# @subfield resources.memory -- (string) memory resources of worker.
deployment: {}
Key | Type | Default | Description |
---|---|---|---|
worker.deployment | object | {} |
deployment of worker |
worker.deployment.replicaCount | int | replicaCount of worker. | |
worker.deployment.resources.cpu | string | cpu resources of worker. | |
worker.deployment.resources.memory | string | memory resources of worker. |
We have values.yaml
template and additional values-<env>.yaml
per environment.
To install the chart, a YAML file that specifies the new values and overwrite the above default parameters are provided per environment:
helm install --name someapp -f values=values-qa.yaml stable/someapp
In this case, values-qa.yaml
contains values that overwrite default values.yaml
. When we run helm-docs
it only reads values.yaml
and output the default chart values, without the qa
. Need ability to pass values
like helm to output proper chart values table.
Might be related to #92
# -- before desc
before: ~
# -- commented desc
#commented: ~
# -- after desc
after: ~
Key | Type | Default | Description |
---|---|---|---|
after | string | nil |
after desc |
before | string | nil |
before desc |
Key | Type | Default | Description |
---|---|---|---|
after | string | nil |
commented desc -- after desc |
before | string | nil |
before desc |
Hi,
Your README generator is really great ! 👍
However we still have to "adapt" our value.yaml
file to provide the field path which is "intrusive" and "error prone".
controller:
# controller.persistentVolumeClaims -- List of persistent volume claims to create
persistentVolumeClaims: []
There is this alternative project which automatically determine the field path : https://github.com/kubepack/chart-doc-gen
controller:
# List of persistent volume claims to create
persistentVolumeClaims: []
Do you think you could be able to provide the same automatic behavior ?
Thanks in advance
Would you be ok to release docker images ?
goreleaser
supports building and pushing docker images.
It would be useful to integrate in a CI pipeline, to ensure the doc is up to date.
Thanks.
Greetings,
I'm opening this issue for feedback to see what people think; maybe it's been opened before. Basically, I would like multi-line YAML blocks to be formatted using <pre>
tags in Markdown rather than the current behavior, which is a single line block using backtick characters.
If I have a multi-line YAML block in values.yaml
file like so:
# -- Security context for the container level.
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65534
This will be rendered as follows in the current version of Helm Docs:
{"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true,"runAsNonRoot":true,"runAsUser":65534}
As multi-line YAML blocks become large, this creates a slight readability problem. The https://github.com/terraform-docs/terraform-docs project handles this in a different way using <pre>
blocks to look like the following directly in the Markdown:
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65534
Here's the HTML of the above as it would be rendered in terraform-docs
style:
<pre>securityContext:<br /> capabilities:<br /> drop:<br /> - ALL<br /> readOnlyRootFilesystem: true<br /> runAsNonRoot: true<br /> runAsUser: 65534</pre>
If you want to see a real example of this, you can check out the https://github.com/cloudposse/terraform-null-label#inputs repository, and under Inputs
, look at the context
block.
What do people think? Would this be preferred?
I would be nice to have the nomenclature of the requirements/dependencies match helm to avoid confusion. Helm documents them as dependencies whereas helm-docs state them as requirements.
-
to make version string like 1.0.1-rc.1 workFor helm chart with Pre-release versions (e.g. 1.0.1-rc.1 or 1.0.1-alpha.0), helm-docs will generate badge markdown like:
![Version: 1.0.1-rc.1](https://img.shields.io/badge/Version-1.0.1-rc.1-informational?style=flat-square)
which will render as (because shields.io
use dash "-" as separators in URL):
helm-docs
should escape dash "-" as "--" according to shields.io
.
Dashes -- → - Dash
Underscores __ → _ Underscore
_ or Space → Space
i.e. the correct badge markdown should be:
![Version: 1.0.1-rc.1](https://img.shields.io/badge/Version-1.0.1--rc.1-informational?style=flat-square)
which will render the followings:
The title of the issue is admittedly a bit weird, but I'm not sure what else is going on with the underlying README.md.gotmpl
file I am using.
Long story short, I am helping to move the cluster-autoscaler Helm chart from the helm/charts repository to the kubernetes/autoscaler repository because of the eventual deprecation of the stable
channel.
I am hoping to make the new README enabled with helm-docs
, but I noticed that when trying to template the README.md
file from that project, I receive errors that some of the templates are "not defined."
The template should render successfully, just like full-template example.
I get error messages for some of the templates, but not all of them:
{{ template "chart.header" . }}
{{ template "chart.description" . }}
{{ template "chart.type" . }}
{{ template "chart.typeLine" . }}
{{ template "chart.typeBadge" . }}
{{ template "chart.appVersion" . }}
{{ template "chart.appVersionLine" . }}
{{ template "chart.appVersionBadge" . }}
{{ template "chart.appVersion" . }}
{{ template "chart.appVersionLine" . }}
{{ template "chart.appVersionBadge" . }}
{{ template "chart.homepage" . }}
{{ template "chart.homepageLine" . }}
{{ template "chart.maintainersHeader" . }}
{{ template "chart.maintainersTable" . }}
{{ template "chart.maintainersSection" . }}
{{ template "chart.sourcesHeader" . }}
{{ template "chart.sourcesList" . }}
{{ template "chart.sourcesSection" . }}
All of the non-working templates receive an error similar to this:
WARN[2020-07-22T17:08:07+02:00] Error generating documentation for chart cluster-autoscaler: template: cluster-autoscaler:9:12: executing "cluster-autoscaler" at <{{template "chart.typeBadge" .}}>: template "chart.typeBadge" not defined
Here's the information of my underlying environment:
version.BuildInfo{Version:"v3.2.4", GitCommit:"0ad800ef43d3b826f31a5ad8dfbb4fe05d143688", GitTreeState:"dirty", GoVersion:"go1.14.3"}
helm-docs version 0.13.0
Are here are the files I used. Note that the README.md.gotmpl
contains all templates that work. Adding any of the Non-working templates
list above results in an error, and does not render.
{{ template "chart.header" . }} {{ template "chart.description" . }} {{ template "chart.type" . }} {{ template "chart.typeLine" . }} ## TL;DR: ```console $ helm repo add autoscaler https://kubernetes.github.io/autoscaler $ helm install autoscaler/cluster-autoscaler --name my-release --set "autoscalingGroups[0].name=your-asg-name,autoscalingGroups[0].maxSize=10,autoscalingGroups[0].minSize=1" ``` ## Introduction This chart bootstraps a cluster-autoscaler deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. ## Prerequisites - Helm 3+ - Kubernetes 1.8+ - [Older versions](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#releases) may work by overriding the `image`. Cluster autoscaler internally simulates the scheduler and bugs between mismatched versions may be subtle. - Azure AKS specific Prerequisites: - Kubernetes 1.10+ with RBAC-enabled. ## Previous Helm Chart The previous `cluster-autoscaler` Helm chart hosted at [helm/charts](https://github.com/helm/charts) has been moved to this repository in accordance with the [Deprecation timeline](https://github.com/helm/charts#deprecation-timeline). Note that a few things have changed between this version and the old version: - This repository **only** supports Helm chart installations using Helm 3+ since the `apiVersion` on the charts has been marked as `v2`. - Previous versions of the Helm chart have not been migrated, and the version was reset to `1.0.0` at the onset. If you are looking for old versions of the chart, it's best to run `helm pull stable/cluster-autoscaler --version ` until you are ready to move to this repository's version. ## Installing the Chart **By default, no deployment is created and nothing will autoscale**. You must provide some minimal configuration, either to specify instance groups or enable auto-discovery. It is not recommended to do both. Either: - Set `autoDiscovery.clusterName` and tag your autoscaling groups appropriately (`--cloud-provider=aws` only) **or** - Set at least one ASG as an element in the `autoscalingGroups` array with its three values: `name`, `minSize` and `maxSize`. To install the chart with the release name `my-release`: ### AWS - Using auto-discovery of tagged instance groups Auto-discovery finds ASGs tags as below and automatically manages them based on the min and max size specified in the ASG. `cloudProvider=aws` only. - Tag the ASGs with keys to match `.Values.autoDiscovery.tags`, by default: `k8s.io/cluster-autoscaler/enabled` and `k8s.io/cluster-autoscaler/` - Verify the [IAM Permissions](#iam) - Set `autoDiscovery.clusterName=` - Set `awsRegion=` - Set `awsAccessKeyID=` and `awsSecretAccessKey=` if you want to [use AWS credentials directly instead of an instance role](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials) ```console $ helm install autoscaler/cluster-autoscaler --name my-release --set autoDiscovery.clusterName= ``` #### Specifying groups manually Without autodiscovery, specify an array of elements each containing ASG name, min size, max size. The sizes specified here will be applied to the ASG, assuming IAM permissions are correctly configured. - Verify the [IAM Permissions](#iam) - Either provide a yaml file setting `autoscalingGroups` (see values.yaml) or use `--set` e.g.: ```console $ helm install autoscaler/cluster-autoscaler --name my-release --set "autoscalingGroups[0].name=your-asg-name,autoscalingGroups[0].maxSize=10,autoscalingGroups[0].minSize=1" ``` #### Auto-discovery For auto-discovery of instances to work, they must be tagged with the keys in `.Values.autoDiscovery.tags`, which by default are `k8s.io/cluster-autoscaler/enabled` and `k8s.io/cluster-autoscaler/` The value of the tag does not matter, only the key. An example kops spec excerpt: ``` apiVersion: kops/v1alpha2 kind: Cluster metadata: name: my.cluster.internal spec: additionalPolicies: node: | [ {"Effect":"Allow","Action":["autoscaling:DescribeAutoScalingGroups","autoscaling:DescribeAutoScalingInstances","autoscaling:DescribeLaunchConfigurations","autoscaling:DescribeTags","autoscaling:SetDesiredCapacity","autoscaling:TerminateInstanceInAutoScalingGroup"],"Resource":"*"} ] ... --- apiVersion: kops/v1alpha2 kind: InstanceGroup metadata: labels: kops.k8s.io/cluster: my.cluster.internal name: my-instances spec: cloudLabels: k8s.io/cluster-autoscaler/enabled: "" k8s.io/cluster-autoscaler/my.cluster.internal: "" image: kops.io/k8s-1.8-debian-jessie-amd64-hvm-ebs-2018-01-14 machineType: r4.large maxSize: 4 minSize: 0 ``` In this example you would need to `--set autoDiscovery.clusterName=my.cluster.internal` when installing. It is not recommended to try to mix this with setting `autoscalingGroups` See [autoscaler AWS documentation](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#auto-discovery-setup) for a more discussion of the setup. ### GCE The following parameters are required: - `autoDiscovery.clusterName=any-name` - `cloud-provider=gce` - `autoscalingGroupsnamePrefix[0].name=your-ig-prefix,autoscalingGroupsnamePrefix[0].maxSize=10,autoscalingGroupsnamePrefix[0].minSize=1` To use Managed Instance Group (MIG) auto-discovery, provide a YAML file setting `autoscalingGroupsnamePrefix` (see values.yaml) or use `--set` when installing the Chart - e.g. ```console $ helm install autoscaler/cluster-autoscaler \ --name my-release \ --set autoDiscovery.clusterName= \ --set cloudProvider=gce \ --set "autoscalingGroupsnamePrefix[0].name=your-ig-prefix,autoscalingGroupsnamePrefix[0].maxSize=10,autoscalingGroupsnamePrefix[0].minSize=1" ``` Note that `your-ig-prefix` should be a _prefix_ matching one or more MIGs, and _not_ the full name of the MIG. For example, to match multiple instance groups - `k8s-node-group-a-standard`, `k8s-node-group-b-gpu`, you would use a prefix of `k8s-node-group-`. In the event you want to explicitly specify MIGs instead of using auto-discovery, set members of the `autoscalingGroups` array directly - e.g. ``` # where 'n' is the index, starting at 0 -- set autoscalingGroups[n].name=https://content.googleapis.com/compute/v1/projects/$PROJECTID/zones/$ZONENAME/instanceGroupManagers/$FULL-MIG-NAME,autoscalingGroups[n].maxSize=$MAXSIZE,autoscalingGroups[n].minSize=$MINSIZE ``` ### Azure AKS The following parameters are required: - `cloudProvider=azure` - `autoscalingGroups[0].name=your-agent-pool,autoscalingGroups[0].maxSize=10,autoscalingGroups[0].minSize=1` - `azureClientID: "your-service-principal-app-id"` - `azureClientSecret: "your-service-principal-client-secret"` - `azureSubscriptionID: "your-azure-subscription-id"` - `azureTenantID: "your-azure-tenant-id"` - `azureClusterName: "your-aks-cluster-name"` - `azureResourceGroup: "your-aks-cluster-resource-group-name"` - `azureVMType: "AKS"` - `azureNodeResourceGroup: "your-aks-cluster-node-resource-group"` ## Uninstalling the Chart To uninstall `my-release`: ```console $ helm uninstall my-release ``` The command removes all the Kubernetes components associated with the chart and deletes the release. > **Tip**: List all releases using `helm list` or start clean with `helm uninstall my-release` ## Additional Configuration ### AWS - IAM The worker running the cluster autoscaler will need access to certain resources and actions: ``` { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "autoscaling:DescribeAutoScalingGroups", "autoscaling:DescribeAutoScalingInstances", "autoscaling:DescribeLaunchConfigurations", "autoscaling:DescribeTags", "autoscaling:SetDesiredCapacity", "autoscaling:TerminateInstanceInAutoScalingGroup" ], "Resource": "*" } ] } ``` - `DescribeTags` is required for autodiscovery. - `DescribeLaunchConfigurations` is required to scale up an ASG from 0. Unfortunately AWS does not support ARNs for autoscaling groups yet so you must use "*" as the resource. More information [here](http://docs.aws.amazon.com/autoscaling/latest/userguide/IAM.html#UsingWithAutoScaling_Actions). ### AWS - IAM Roles for Service Accounts (IRSA) For Kubernetes clusters that use Amazon EKS, the service account can be configured with an IAM role using [IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) to avoid needing to grant access to the worker nodes for AWS resources. In order to accomplish this, you will first need to create a new IAM role with the above mentions policies. Take care in [configuring the trust relationship](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html#iam-role-configuration) to restrict access just to the service account used by cluster autoscaler. Once you have the IAM role configured, you would then need to `--set rbac.serviceAccountAnnotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::123456789012:role/MyRoleName` when installing. ## Troubleshooting The chart will succeed even if the container arguments are incorrect. A few minutes after starting `kubectl logs -l "app=aws-cluster-autoscaler" --tail=50` should loop through something like ``` polling_autoscaler.go:111] Poll finished static_autoscaler.go:97] Starting main loop utils.go:435] No pod using affinity / antiaffinity found in cluster, disabling affinity predicate for this loop static_autoscaler.go:230] Filtering out schedulables ``` If not, find a pod that the deployment created and `describe` it, paying close attention to the arguments under `Command`. e.g.: ``` Containers: cluster-autoscaler: Command: ./cluster-autoscaler --cloud-provider=aws # if specifying ASGs manually --nodes=1:10:your-scaling-group-name # if using autodiscovery --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/ --v=4 ``` ### PodSecurityPolicy Though enough for the majority of installations, the default PodSecurityPolicy _could_ be too restrictive depending on the specifics of your release. Please make sure to check that the template fits with any customizations made or disable it by setting `rbac.pspEnabled` to `false`. {{ template "chart.valuesSection" . }}
apiVersion: v2
appVersion: 1.18.1
description: Scales Kubernetes worker nodes within autoscaling groups.
engine: gotpl
home: https://github.com/kubernetes/autoscaler
icon: https://github.com/kubernetes/kubernetes/blob/master/logo/logo.png
maintainers:
- email: [email protected]
name: gjtempleton
- email: [email protected]
name: mgoodness
- email: [email protected]
name: sc250024
- email: [email protected]
name: yurrriq
name: cluster-autoscaler
sources:
- https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler
- https://github.com/spotinst/kubernetes-autoscaler/tree/master/cluster-autoscaler
type: application
version: 1.0.0
## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
# affinity -- Affinity for pod assignment
affinity: {}
autoDiscovery:
# Only cloudProvider `aws` and `gce` are supported by auto-discovery at this time
# AWS: Set tags as described in https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#auto-discovery-setup
# autoDiscovery.clusterName -- Enable autodiscovery for name in ASG tag (only `cloudProvider=aws`). Must be set for `cloudProvider=gce`, but no MIG tagging required.
clusterName: # cluster.local
# autoDiscovery.tags -- ASG tags to match, run through `tpl`.
tags:
- k8s.io/cluster-autoscaler/enabled
- k8s.io/cluster-autoscaler/{{ .Values.autoDiscovery.clusterName }}
# - kubernetes.io/cluster/{{ .Values.autoDiscovery.clusterName }}
# autoscalingGroups -- For AWS. At least one element is required if not using `autoDiscovery`. For example:
# <pre>
# - name: asg1<br />
# maxSize: 2<br />
# minSize: 1
# </pre>
autoscalingGroups: []
# - name: asg1
# maxSize: 2
# minSize: 1
# - name: asg2
# maxSize: 2
# minSize: 1
# autoscalingGroupsnamePrefix -- For GCE. At least one element is required if not using `autoDiscovery`. For example:
# <pre>
# - name: ig01<br />
# maxSize: 10<br />
# minSize: 0
# </pre>
autoscalingGroupsnamePrefix: []
# - name: ig01
# maxSize: 10
# minSize: 0
# - name: ig02
# maxSize: 10
# minSize: 0
# awsAccessKeyID -- AWS access key ID ([if AWS user keys used](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials))
awsAccessKeyID: ""
# awsRegion -- AWS region (required if `cloudProvider=aws`)
awsRegion: us-east-1
# awsSecretAccessKey -- AWS access secret key ([if AWS user keys used](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials))
awsSecretAccessKey: ""
# azureClientID -- Service Principal ClientID with contributor permission to Cluster and Node ResourceGroup.
# Required if `cloudProvider=azure`
azureClientID: ""
# azureClientSecret -- Service Principal ClientSecret with contributor permission to Cluster and Node ResourceGroup.
# Required if `cloudProvider=azure`
azureClientSecret: ""
# azureResourceGroup -- Azure resource group that the cluster is located.
# Required if `cloudProvider=azure`
azureResourceGroup: ""
# azureSubscriptionID -- Azure subscription where the resources are located.
# Required if `cloudProvider=azure`
azureSubscriptionID: ""
# azureTenantID -- Azure tenant where the resources are located.
# Required if `cloudProvider=azure`
azureTenantID: ""
# azureVMType -- Azure VM type.
azureVMType: "AKS"
# azureClusterName -- Azure AKS cluster name.
# Required if `cloudProvider=azure`
azureClusterName: ""
# azureNodeResourceGroup -- Azure resource group where the cluster's nodes are located, typically set as `MC_<cluster-resource-group-name>_<cluster-name>_<location>`.
# Required if `cloudProvider=azure`
azureNodeResourceGroup: ""
# azureUseManagedIdentityExtension -- Whether to use Azure's managed identity extension for credentials. If using MSI, ensure subscription ID and resource group are set.
azureUseManagedIdentityExtension: false
# cloudConfigPath -- Configuration file for cloud provider.
cloudConfigPath: /etc/gce.conf
# cloudProvider -- The cloud provider where the autoscaler runs.
# Currently only `gce`, `aws`, and `azure` are supported.
# `aws` supported for AWS. `gce` for GCE. `azure` for Azure AKS.
cloudProvider: aws
# containerSecurityContext -- [Security context for container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
containerSecurityContext: {}
# capabilities:
# drop:
# - ALL
# dnsPolicy -- Defaults to `ClusterFirst`. Valid values are:
# `ClusterFirstWithHostNet`, `ClusterFirst`, `Default` or `None`.
# If autoscaler does not depend on cluster DNS, recommended to set this to `Default`.
dnsPolicy: ClusterFirst
## Priorities Expander
# expanderPriorities -- The expanderPriorities is used if `extraArgs.expander` is set to `priority` and expanderPriorities is also set with the priorities.
# If `extraArgs.expander` is set to `priority`, then expanderPriorities is used to define cluster-autoscaler-priority-expander priorities.
# See: https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/expander/priority/readme.md
expanderPriorities: {}
# extraArgs -- Additional container arguments.
extraArgs:
logtostderr: true
stderrthreshold: info
v: 4
# write-status-configmap: true
# leader-elect: true
# skip-nodes-with-local-storage: false
# expander: least-waste
# scale-down-enabled: true
# balance-similar-node-groups: true
# min-replica-count: 2
# scale-down-utilization-threshold: 0.5
# scale-down-non-empty-candidates-count: 5
# max-node-provision-time: 15m0s
# scan-interval: 10s
# scale-down-delay-after-add: 10m
# scale-down-delay-after-delete: 0s
# scale-down-delay-after-failure: 3m
# scale-down-unneeded-time: 10m
# skip-nodes-with-local-storage: false
# skip-nodes-with-system-pods: true
# extraEnv -- Additional container environment variables.
extraEnv: {}
# fullnameOverride -- String to fully override `cluster-autoscaler.fullname` template.
fullnameOverride: ""
image:
# image.repository -- Image repository
repository: us.gcr.io/k8s-artifacts-prod/autoscaling/cluster-autoscaler
# image.tag -- Image tag
tag: v1.18.1
# image.pullPolicy -- Image pull policy
pullPolicy: IfNotPresent
## Optionally specify an array of imagePullSecrets.
## Secrets must be manually created in the namespace.
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
##
# image.pullSecrets -- Image pull secrets
pullSecrets: []
# - myRegistrKeySecretName
# kubeTargetVersionOverride -- Allow overridding the `.Capabilities.KubeVersion.GitVersion` check. Useful for `helm template` commands.
kubeTargetVersionOverride: ""
# nameOverride -- String to partially override `cluster-autoscaler.fullname` template (will maintain the release name)
nameOverride: ""
# nodeSelector -- Node labels for pod assignment. Ref: https://kubernetes.io/docs/user-guide/node-selection/.
nodeSelector: {}
# podAnnotations -- Annotations to add to each pod.
podAnnotations: {}
# podDisruptionBudget -- Pod disruption budget.
podDisruptionBudget:
maxUnavailable: 1
# minAvailable: 2
# podLabels -- Labels to add to each pod.
podLabels: {}
# priorityClassName -- priorityClassName
priorityClassName: ""
rbac:
# rbac.create -- If `true`, create and use RBAC resources.
create: true
# rbac.pspEnabled -- If `true`, creates and uses RBAC resources required in the cluster with [Pod Security Policies](https://kubernetes.io/docs/concepts/policy/pod-security-policy/) enabled.
# Must be used with `rbac.create` set to `true`.
pspEnabled: false
serviceAccount:
# rbac.serviceAccount.annotations -- Additional Service Account annotations.
annotations: {}
# rbac.serviceAccount.create -- If `true` and `rbac.create` is also true, a Service Account will be created.
create: true
# rbac.serviceAccount.name -- The name of the ServiceAccount to use. If not set and create is `true`, a name is generated using the fullname template.
name: ""
# replicaCount -- Desired number of pods
replicaCount: 1
# resources -- Pod resource requests and limits.
resources: {}
# limits:
# cpu: 100m
# memory: 300Mi
# requests:
# cpu: 100m
# memory: 300Mi
# securityContext -- [Security context for pod](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
securityContext: {}
# runAsNonRoot: true
# runAsUser: 1001
# runAsGroup: 1001
service:
# service.annotations -- Annotations to add to service
annotations: {}
# service.externalIPs -- List of IP addresses at which the service is available. Ref: https://kubernetes.io/docs/user-guide/services/#external-ips.
externalIPs: []
# service.loadBalancerIP -- IP address to assign to load balancer (if supported).
loadBalancerIP: ""
# service.loadBalancerSourceRanges -- List of IP CIDRs allowed access to load balancer (if supported).
loadBalancerSourceRanges: []
# service.servicePort -- Service port to expose.
servicePort: 8085
# service.portName -- Name for service port.
portName: http
# service.type -- Type of service to create.
type: ClusterIP
## Are you using Prometheus Operator?
serviceMonitor:
# serviceMonitor.enabled -- If true, creates a Prometheus Operator ServiceMonitor.
enabled: false
# serviceMonitor.interval -- Interval that Prometheus scrapes Cluster Autoscaler metrics.
interval: 10s
# serviceMonitor.namespace -- Namespace which Prometheus is running in.
namespace: monitoring
## [Prometheus Selector Label](https://github.com/helm/charts/tree/master/stable/prometheus-operator#prometheus-operator-1)
## [Kube Prometheus Selector Label](https://github.com/helm/charts/tree/master/stable/prometheus-operator#exporters)
# serviceMonitor.selector -- Default to kube-prometheus install (CoreOS recommended), but should be set according to Prometheus install.
selector:
release: prometheus-operator
# serviceMonitor.path -- The path to scrape for metrics; autoscaler exposes `/metrics` (this is standard)
path: /metrics
# tolerations -- List of node taints to tolerate (requires Kubernetes >= 1.6).
tolerations: []
# updateStrategy -- [Deployment update strategy](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy)
updateStrategy: {}
# rollingUpdate:
# maxSurge: 1
# maxUnavailable: 0
# type: RollingUpdate
In my freshrss chart, I have an array of minutes for a cronjob to run, which by default is 23 and 53
freshrss:
# freshrss.cron_min - What minutes of the hour should the cron script run
cron_min: [23, 53]
produces
Key | Type | Default | Description |
---|---|---|---|
freshrss.cron_min[0] | int | 23 |
|
freshrss.cron_min[1] | int | 53 |
Is there a way to tell it to document the entire array not the specific entries in the array?
Can we configure what is set in the default value column from comments ?
Sometimes the default value is quite large (a configuration file for example) and i would like to put a short description like see in values.yaml
rather than the raw whole config file content.
Hey!
Would it be possible to include a flag to specify a new name for the generated markdown files ? :) I didn't find a way to change the names to something other than "README.md", and some other readme's of the project I'm using this tool for are getting overwritten...
Thanks!
Following this guide for library charts there is no value file and no templates that produce yaml directly but only helpers.
It would be nice if helm-docs
wasn't skipping the README generation upon missing values file but still render everything from the Chart.yaml meta-data so we get this part documented automatically.
This could either be implemented using a --library-chart
etc. flag or as a breaking change where it doesn't skip the generation when the values file is missing.
Hello and thanks for all the effort you put into this. It already saved me hours of typing all the values.yaml tables.
Now my issue is, that a generated default README.md fails the markdownlint of https://github.com/DavidAnson/markdownlint in default configuration.
E.g.:
markdownlint README.md
README.md:1 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "sys11prometheus-operator"]
README.md:7 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2]
README.md:8 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 3]
README.md:9 MD003/heading-style/header-style Heading style [Expected: setext; Actual: atx]
README.md:13:81 MD013/line-length Line length [Expected: 80; Actual: 85]
README.md:13:3 MD034/no-bare-urls Bare URL used [Context: "https://kubernetes-charts.stor..."]
README.md:15 MD003/heading-style/header-style Heading style [Expected: setext; Actual: atx]
README.md:19:81 MD013/line-length Line length [Expected: 80; Actual: 98]
README.md:20:81 MD013/line-length Line length [Expected: 80; Actual: 102]
README.md:21:81 MD013/line-length Line length [Expected: 80; Actual: 100]
README.md:22:81 MD013/line-length Line length [Expected: 80; Actual: 104]
README.md:23:81 MD013/line-length Line length [Expected: 80; Actual: 133]
README.md:24:81 MD013/line-length Line length [Expected: 80; Actual: 135]
README.md:30:81 MD013/line-length Line length [Expected: 80; Actual: 82]
README.md:31:81 MD013/line-length Line length [Expected: 80; Actual: 90]
README.md:34:81 MD013/line-length Line length [Expected: 80; Actual: 83]
README.md:39:81 MD013/line-length Line length [Expected: 80; Actual: 88]
README.md:40:81 MD013/line-length Line length [Expected: 80; Actual: 86]
README.md:41:81 MD013/line-length Line length [Expected: 80; Actual: 89]
README.md:42:81 MD013/line-length Line length [Expected: 80; Actual: 87]
README.md:50:81 MD013/line-length Line length [Expected: 80; Actual: 96]
README.md:51:81 MD013/line-length Line length [Expected: 80; Actual: 87]
README.md:52:81 MD013/line-length Line length [Expected: 80; Actual: 105]
README.md:53:81 MD013/line-length Line length [Expected: 80; Actual: 94]
README.md:54:81 MD013/line-length Line length [Expected: 80; Actual: 98]
README.md:55:81 MD013/line-length Line length [Expected: 80; Actual: 95]
README.md:56:81 MD013/line-length Line length [Expected: 80; Actual: 99]
README.md:57:81 MD013/line-length Line length [Expected: 80; Actual: 90]
README.md:59:81 MD013/line-length Line length [Expected: 80; Actual: 99]
README.md:60:81 MD013/line-length Line length [Expected: 80; Actual: 100]
README.md:61:81 MD013/line-length Line length [Expected: 80; Actual: 91]
README.md:62:81 MD013/line-length Line length [Expected: 80; Actual: 109]
README.md:63:81 MD013/line-length Line length [Expected: 80; Actual: 133]
README.md:64:81 MD013/line-length Line length [Expected: 80; Actual: 136]
I know that I could write my own template or configure the yamllint to not fail on the default generated README.md (e.g. I guess I can ignore the line too long ones). I was just wondering whether you ever tried to lint the generated YAML and if you were open to changing the default template?
If so I am willing to provide a patch to fix the default template as far as possible.
Regards
I wondered if I'm missing anything - I was hoping to have my values table outputted in the same order that the yaml is laid out. Is that possible?
Dear maintainers,
Firstly, this is a great tool for producing the documentation. In my case, i have a helm chart with lot of dependencies packed in a tar.gz file. Is it possible to generate one README file with the values from all the dependent charts instead of the README recursively generated in all the sub-chart directories.
It would be awesome to have a Github Action that will ensure people update chart READMEs on every PR 😃
It seems impossible at the moment to customize the directory of the generated readme.
I have my helm chart in a sub-folder, and as a result, the README is always generated in that subfolder.
e.g:
my helm chart is located in the ./helm
subfolder. My config looks like this:
- repo: https://github.com/norwoodj/helm-docs
rev: v1.4.0
hooks:
- id: helm-docs
args:
- --chart-search-root=helm
- --template-files=../README.md.gotmpl
I want to keep my helm
directory clean, so I already managed to keep the template out of the helm folder by using ../README.md.gotmpl
.
Now, how do I prevent the readme of being generated in the ./helm
folder, and just in my top-level folder? Specifying the output destination of a generated file, doesn't feel like an uncommon thing...
# -- Field description
# @default -- Default value description
field:
Will output: | field | string | `nil` | Field description |
Whereas
# -- Field description
# @default -- Default value description
field: ""
Outputs: | field | string | Default value description | Field description |
In order to make it easier for folks to install helm-docs, we should add a homebrew tap so that one can simply brew install
the tool.
Hi @norwoodj .
First, I would like to say thanks for this great piece of tool. I can imagine I will use it a lot.
I would like to propose some feature addition that rises from the needs of maintaining my own helm charts.
I managed helm chart recipe where some of the services are needed as dependencies to other charts.
Some chart bootstrap other charts from one single values.yaml
file. To support some customization in the chart dependencies, some of the values needs to be clearly defined and interlinked (definition of possible values for chart A may reuse or refer the original definition of values in chart B). To support this kind of use case, I propose the following feature additions:
Some dependent chart's values needs to be injected from original chart via Go template string. A value that need a go template string can be like this:
global:
siteName: 'mysite.org'
awesomeApp:
enabled: true
siteUrl: |
https://{{ .Values.global.sitename }}
When chart was generated, the value awesomeApp.siteUrl
is set dynamically at generation time as https://mysite.org
. However, currently helm-docs will generate the default value of awesomeApp.siteUrl
as a JSON escaped string. This doesn't look easy to understand because it will only be a one line string with some escaped character.
I would like to be able to show the default value as:
siteUrl: |
https://{{ .Values.global.sitename }}
This way, user understands that the value expects a Go template string.
In some cases, rendering the escaped JSON values looks very complicated. There is also another reason where I want the user to replace a value with a valid YAML structure, but since the default value is rendered as JSON, it looks misleading.
If the values.yaml
looks like this:
parent:
# -- child description
child:
name: "honk"
age: 13
hobby: "sleeping"
I want the default value to be rendered in YAML like this for the key parent.child
:
name: "honk"
age: 13
hobby: "sleeping"
Currently, the value types are recognized directly from the YAML structure.
However in some cases, the value types have a clear defined structure that can be referenced elsewhere. Like k8s docs, other chart, or simple structure like email
, URL
, filepath
, csv
etc.
I would like to be able to put my own custom type like this:
# -- (string/email) This is a user email type
email: [email protected]
# -- (string/url) This has to be formatted as URL
url: https://somesite.org
At least these types can be parsed and rendered in the values table.
Even if two values use string, that doesn't mean it should be rendered the same way in the default value column.
In some chart, I can put my own configuration file inside the values.yaml
so that it can be included in the configmap.
All of it are string value, but we can improve the rendering to match the language syntax.
I propose we add another annotation: @notationType
that can tell you what type of rendering it we should use.
# -- This is string, but should be rendered as python file
# @notationType -- python
djangoSettings: |
import os
# something pythony
# -- This is string, but can be rendered as nginx config file
# @notationType -- nginx
nginxConfig: |
# nginx server block
server {
location / {
# some nginx config
}
}
The rendering itself is a separate issue, but I was hoping that the @notationType
was parsed first and available inside the template.
My above use case seems to need the table to be generated directly as HTML tags.
I can do it myself, totally separate from helm-docs
, however if this can be merged and supported, it would be good.
Basically the current values table are rendered using Github Markdown, from markdown syntax. But if we can provide HTML tags rendering, this would be possible:
<pre>
tag, multiline. So we can pretty print the default behaviour of rendering the default values as JSON<pre>
tag directly.<td>
or <tr>
tag of the value rows can create anchor that can be referenced inside the markdown, or across the page. So my chart A can refer to value documentation at chart B.Type
columns, so that it will hyperlinked to the data structure/value structure definition somewhereDefault
value columns, so that it appropriately consider @notationType
and render suitable color syntax or formatI think, we can keep the usual value section in markdown and this HTML tables as separate template definition.
Currently if a template is not found the template lookup:
This is somewhat counterintuitive to me, because helm-docs can be used to generate README files for multiple charts. Having custom per-chart overrides sounds like a perfectly valid use-case.
My suggestion is:
I'd be happy to provide a PR.
Hey and thanks for this tool, it makes my life easier :)
I was wondering how I can use the pre-commit hook with a GitHub action? If I use the official GitHub action for pre-commit and install helm-docs
like this, it fails with Please install helm-docs to run the pre-commit hook! https://github.com/norwoodj/helm-docs#installation
:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v1
with:
go-version: '1.16.4'
- name: Install helm-docs
run: GO111MODULE=on go get github.com/norwoodj/helm-docs/cmd/helm-docs
- run: helm docs
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: pre-commit/[email protected]
Is this due to the pre-commit action being run in its own container, can you maybe help me out here?
I have created a README.md.gotmpl
that follows the official helm charts repo more closely, e.g. README.md.
Unfortunately, not all information is present in the Chart.yml
and therefore it's usually required to add more details to the README.md. This will then make it hard to update the README.md
through helm-docs upon changes in the helm chart.
It would be great to have the ability to regenerate the README.md
upon changes.
I suggest having a helm-docs
configuration file, e.g. .helm-docs.yaml
which can be located in each chart repo with relevant text snippets to be added to the final README.md
.
Example:
README.md.gotmpl
:
# {{ .Name }}
helm install {{ .cfg.ChartRepository }}/{{ .Name }}
{{ .cfg.SomeRandomText }}
.helm-docs.yaml
:
ChartRepository: mychartrepo
SomeRandomText: |
Lorem Ipsum
First off, let me say this is an awesome project! This saves so much time, so thank you for doing it!
I'm submitting a ...
Do you want to request a feature or report a bug?
This is a feature request to have the CLI read from a README.md.tpl
. The idea is that the user can then write some custom text for their README.md file, while also keeping the nice autogenerated Helm name, description, and variables.
It would be nice if the CLI could read from a file README.md.tpl
, which is defined by the user, specified in a command line flag. That way, something like the following could be done:
README.md.tpl
{{ block "chart_name" }}
{{ block "chart_description" }}
# My custom section 1
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non semper purus, et aliquet mauris. Quisque ligula metus, semper maximus faucibus eu, venenatis et augue. Aenean eget dapibus mi. Mauris sed nibh sit amet nibh scelerisque convallis vitae et nisl. Aliquam vulputate dolor et vehicula venenatis. Sed quis nisi a massa venenatis aliquet. Maecenas sit amet lorem ipsum. Proin iaculis justo et dolor viverra, eu consequat ex pellentesque. Etiam rhoncus, nisl nec egestas pretium, massa magna tristique metus, eu euismod erat lacus non nisi. Donec quis rhoncus sapien. Praesent at venenatis tellus. Integer cursus nec massa quis scelerisque. Nam luctus urna vitae gravida viverra. Nunc mi turpis, tincidunt id condimentum sed, egestas et magna. Nam id gravida est. Integer ultricies dapibus quam nec commodo.
## My custom subsection
Praesent at venenatis tellus. Integer cursus nec massa quis scelerisque. Nam luctus urna vitae gravida viverra. Nunc mi turpis, tincidunt id condimentum sed, egestas et magna. Nam id gravida est. Integer ultricies dapibus quam nec commodo.
> ```yaml
> some:
> important:
> example:
> foo: bar
> ```
{{ block "chart_variables" }}
The helm-docs
CLI would then populate the chart_name
, chart_description
, and chart_variables
configuration blocks from chart specifications. The custom text in the middle (or wherever the user chooses) will be kept, resulting in a more complete README.md file for Helm charts.
The command might be helm-docs --template README.me.tpl
, and the template file would follow the Golang specification.
Currently, the README.md file is written from the helm-docs
command reading only the Chart.yaml
file.
For complex Helm charts where additional resource files and manifest templates are split into multiple files and directories, it can be useful to allow programatic enumeration of the files within the chart to help generate documentation.
For example I have a large chart that splits up many micro-service components into ./templates/components/COMPONENT.yaml
.
This is useful for splitting discrete tables of .Values
documentation out per component. At the moment I have to create a list with all the component names in manually so that it can be looped around.
Adding a .Files
interface in the same way that Helm does would be very helpful. Specifically being able to use .Files.Glob
would be fantastic.
https://helm.sh/docs/chart_template_guide/accessing_files/
I have included an example of the specific use-case. Just imagine it with dozens more components instead of 5. :-)
{{- $dependencies := list "dep1" "dep2" "dep3" "dep4" "dep4" }}
{{- $components := list }}
{{- $components := append $components "component1" }}
{{- $components := append $components "component2" }}
{{- $components := append $components "component3" }}
{{- $components := append $components "component4" }}
{{- $components := append $components "component5" }}
{{- $componentDefaults := list "replicaCount" }}
{{- $componentDefaults := append $componentDefaults "replicaCount" }}
{{- $componentDefaults := append $componentDefaults "image" }}
{{- $componentDefaults := append $componentDefaults "imagePullSecrets" }}
{{- $componentDefaults := append $componentDefaults "serviceAccount" }}
{{- $componentDefaults := append $componentDefaults "podAnnotations" }}
{{- $componentDefaults := append $componentDefaults "podSecurityContext" }}
{{- $componentDefaults := append $componentDefaults "securityContext" }}
{{- $componentDefaults := append $componentDefaults "ingress" }}
{{- $componentDefaults := append $componentDefaults "resources" }}
{{- $componentDefaults := append $componentDefaults "autoscaling" }}
{{- $componentDefaults := append $componentDefaults "nodeSelector" }}
{{- $componentDefaults := append $componentDefaults "tolerations" }}
{{- $componentDefaults := append $componentDefaults "affinity" }}
## Global Values
| Key | Type | Default | Description |
|-----|------|---------|-------------|
{{- range .Values }}
{{- if has ((splitList "." .Key) | first) $dependencies | not }}
{{- if has ((splitList "." .Key) | first) $componentDefaults | not }}
{{- if has ((splitList "." .Key) | first) $components | not }}
| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} |
{{- end }}
{{- end }}
{{- end }}
{{- end }}
## Default Values
| Key | Type | Default | Description |
|-----|------|---------|-------------|
{{- range .Values }}
{{- if has ((splitList "." .Key) | first) $componentDefaults }}
| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} |
{{- end }}
{{- end }}
## Component Values
| Key | Type | Default | Description |
|-----|------|---------|-------------|
{{- range .Values }}
{{- $firstPart := (splitList "." .Key) | first }}
{{- $secondPart := (splitList "." .Key) | rest | first }}
{{- if has $firstPart $components }}
{{- if has $secondPart $componentDefaults | not }}
{{- if has ((splitList "." .Key) | first) $componentDefaults | not }}
| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} |
{{- end }}
{{- end }}
{{- end }}
{{- end }}
## Sub-chart Dependency Values
| Key | Type | Default | Description |
|-----|------|---------|-------------|
{{- range .Values }}
{{- if has ((splitList "." .Key) | first) $dependencies }}
| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} |
{{- end }}
{{- end }}
@norwoodj This is a feature request / conversational issue. In a sense, it's the opposite of the #12 issue filed by @knackaron.
How easy / difficult would it be to also document subcharts defined in the requirements.yaml
file ? I know that typically this is not done. However, I'm in the process of writing a common Helm chart, and being able to document the common chart's values.yaml
file, but include it in a parent chart, would be useful.
What do you think?
v1 made it unnecessary to specify the entire value path to generate the documentation, which is great! It would be even more convenient if the '---' were no longer required either. Ie:
controller:
# -- Configure the healthcheck for the ingress controller
livenessProbe:
httpGet:
# -- This is the liveness check endpoint
path: /healthz
Becomes:
controller:
# Configure the healthcheck for the ingress controller
livenessProbe:
httpGet:
# This is the liveness check endpoint
path: /healthz
This helps keep the values files more readable/easier to add documentation.
When specifying a type but leaving description empty, like this:
controller:
# -- (int)
replicas:
helm-docs panics:
time="2021-07-30T19:02:11Z" level=info msg="Generating README Documentation for chart /helm-docs"
panic: runtime error: slice bounds out of range [6:5]
goroutine 18 [running]:
github.com/norwoodj/helm-docs/pkg/document.parseNilValueType(0xc0002fd000, 0x39, 0xc0001bd9f5, 0x5, 0x0, 0x0, 0xc0001bd9f5, 0x5, 0x0, 0x0, ...)
/home/runner/work/helm-docs/helm-docs/pkg/document/values.go:87 +0x257
github.com/norwoodj/helm-docs/pkg/document.createValueRow(0xc0002fd000, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0001bd9f5, 0x5, ...)
/home/runner/work/helm-docs/helm-docs/pkg/document/values.go:154 +0x4a9
github.com/norwoodj/helm-docs/pkg/document.createValueRowsFromField(0xc0002fd000, 0x39, 0xc000214aa0, 0xc000214b40, 0xc00016bd40, 0x1, 0xc0003076c0, 0x1, 0x1, 0x0, ...)
/home/runner/work/helm-docs/helm-docs/pkg/document/values.go:317 +0x914
github.com/norwoodj/helm-docs/pkg/document.createValueRowsFromObject(0xc0002dcf20, 0x17, 0xc000214460, 0xc000214500, 0xc00016bd40, 0x1, 0xc0003072d0, 0x1, 0x1, 0x0, ...)
/home/runner/work/helm-docs/helm-docs/pkg/document/values.go:282 +0x6f0
github.com/norwoodj/helm-docs/pkg/document.createValueRowsFromField(0xc0002dcf20, 0x17, 0xc000214460, 0xc000214500, 0xc00016bd40, 0x1, 0xc0003072d0, 0x1, 0x1, 0x0, ...)
/home/runner/work/helm-docs/helm-docs/pkg/document/values.go:303 +0x152
github.com/norwoodj/helm-docs/pkg/document.createValueRowsFromObject(0xc00029d310, 0xb, 0xc000211e00, 0xc000211ea0, 0xc00016bd40, 0x1, 0xc000304000, 0x3d, 0x49, 0x0, ...)
/home/runner/work/helm-docs/helm-docs/pkg/document/values.go:282 +0x6f0
github.com/norwoodj/helm-docs/pkg/document.createValueRowsFromField(0xc00029d310, 0xb, 0xc000211e00, 0xc000211ea0, 0xc00016bd40, 0x1, 0x52, 0xaa, 0x49, 0x0, ...)
/home/runner/work/helm-docs/helm-docs/pkg/document/values.go:303 +0x152
github.com/norwoodj/helm-docs/pkg/document.createValueRowsFromObject(0x0, 0x0, 0x0, 0xc0001cb720, 0xc00016bd40, 0x1, 0x69a605, 0xc0002ca800, 0x203000, 0x40d630, ...)
/home/runner/work/helm-docs/helm-docs/pkg/document/values.go:282 +0x6f0
github.com/norwoodj/helm-docs/pkg/document.createValueRowsFromField(0x0, 0x0, 0x0, 0xc0001cb720, 0xc00016bd40, 0x1, 0xc0001c52b0, 0xc0001213e8, 0x69812f, 0xc0001213f8, ...)
/home/runner/work/helm-docs/helm-docs/pkg/document/values.go:303 +0x152
github.com/norwoodj/helm-docs/pkg/document.getSortedValuesTableRows(0xc0001cb720, 0xc00016bd40, 0x6ff22eecfa3e7f8b, 0x6f0000c00016ea00, 0x6f00000000000030, 0x1, 0x6ff22eecfa3e7f8b)
/home/runner/work/helm-docs/helm-docs/pkg/document/model.go:32 +0x65
github.com/norwoodj/helm-docs/pkg/document.getChartTemplateData(0xc0000b7f08, 0x2, 0xc0000b7f5a, 0x6, 0xc0000b7fb0, 0x9, 0xc0001bc004, 0x6, 0x0, 0xc000114d20, ...)
/home/runner/work/helm-docs/helm-docs/pkg/document/model.go:85 +0xcb
github.com/norwoodj/helm-docs/pkg/document.PrintDocumentation(0xc0000b7f08, 0x2, 0xc0000b7f5a, 0x6, 0xc0000b7fb0, 0x9, 0xc0001bc004, 0x6, 0x0, 0xc000114d20, ...)
/home/runner/work/helm-docs/helm-docs/pkg/document/generate.go:44 +0x2bc
main.retrieveInfoAndPrintDocumentation(0x889ba5, 0x1, 0xc0000b79c0, 0xa, 0xc0000978d0, 0x1, 0x1, 0xc0000b7ed0, 0x6010100)
/home/runner/work/helm-docs/helm-docs/cmd/helm-docs/main.go:26 +0x2d5
created by main.helmDocs
/home/runner/work/helm-docs/helm-docs/cmd/helm-docs/main.go:69 +0x4f1
I would like to use only one template for my charts with installation instructions like this:
$ helm install my-release stable/{{ template "chart.name" . }}
Is it possible to generate the table of the values as a collection of tables if we define within the values.yaml
file the different sections
Here is what it is generated by default
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| deployment.containerPort | int | `8080` | |
...
from the following definition
deployment:
containerPort: 8080
Generate a section
level for a yaml root
element
## Deployment
Deployment yaml resource containing the parameters to configure the containers, initContainers, volumes, ....
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| containerPort | int | `8080` | |
using the following convention:
include a comment : # Section: xxxxx
before a root element where the # Section
will allow the tool to create a markdown ## Title
containing the name of the field defined hereafter = deployment
and using xxxxxx
as text paragraph.
# Section: Deployment yaml resource containing the parameters to configure the containers, initContainers, volumes, ....
deployment:
containerPort: 8080
As per the documentation, it says below we should be able to generate readme with description from the below example
livenessProbe:
httpGet:
# -- This is the liveness check endpoint
path: /healthz
port: http
When I generate using docker image docker run --rm --volume "$(pwd):/helm-docs" -u $(id -u) jnorwood/helm-docs:latest --dry-run
ReadME generated but the description is not populated as described in the documentation
We should allow non-empty lists and maps to be included in the values table with descriptions. This issue asks that we implement the following behavior for values table generation:
default
field for lists and objects in this case should be a jsonified string of the fieldAn example:
exampleObjectNoDescriptions:
key: value
exampleListNoDescriptions:
- key: value
# exampleObjectDescription -- this object will be documented
exampleObjectDescription:
keyNoDescription: value
# exampleObjectDescription.keyWithDescription -- this object key will be documented
keyWithDescription: value
# exampleListDescription -- this list will be documented
exampleListDescription:
- keyNoDesciption: value
# exampleListDescription[1].keyWithDescription -- this list item key will be documented
- keyWithDescription: value
# exampleListDescription[2] -- this list item will be documented
- listItemWithDescription: value
Produces
Key | Type | Default | Description |
---|---|---|---|
exampleObjectNoDescriptions.key | string | "value" | |
exampleListNoDesciptions[0].key | string | "value" | |
exampleObjectDescription | object | {"keyNoDescription": "value", "keyWithDescription": "value"} |
this object will be documented |
exampleObjectDescription.keyWithDescription | string | "value" | this object key will be documented |
exampleListDescription | list | [{"keyNoDescription": "value"}, {"keyWithDescription": "value"}, {"listItemWithDescription": "value"}] |
this list will be documented |
exampleListDescription[1].keyWithDescription | string | "value" | this list item key will be documented |
exampleListDescription[2] | object | {"listItemWithDescription": "value"} |
this list item will be documented |
Note how exampleListDescription.keyNoDesciption
and exampleObjectDescription.keyNoDescription
aren't documented because the containing object and list themselves have description comments, but the other contained keys are documented because they do have description comments.
Documention doesn't show anything related to Windows OS. Is it supported on windows os or with subsystem on Linux?
Hello,
Could you please inform me about plans with native support apple m1 cpu?
Hello,
Question:
I wonder whether there is a way to change the order in the columns or not ?
I would like to switch description
and default value
columns.
Many thanks
It would be great if helm-docs
can also generate the values.schema.json
. While one could argue helm-docs
should only generate the Markdown I feel it's perfectly equipped to generate JSON schema especially with the description field.
I'm using https://github.com/karuppiah7890/helm-schema-gen atm but looking at the code it basically doesn't do anything really (see here).
It's possible to provide a schema for a Helm chart via values.schema.json
.
The schema specifies the structure of the chart along with types and descriptions of variables.
The type field would help with properties such as lists of objects, which the documentation generation currently doesn't have a good method of rendering.
The description field in the schema would be especially useful in large charts with areas of reuse as you would be able to enter a description once when specify a definition.
If there is a schema present then validating the values.yaml
before process eliminates a large number of edge cases to worry about.
Assuming the values.yaml
is valid then the docs should render the distinct list of fields from both values.schema.json
and values.yaml
.
If both a description in the schema is present along with a comment in the values.yaml
then the comment should probably take precedence.
When subcharts are part of a Git repo and are only included for distribution (e.g., subchart as a Git submodule), helm-docs should have an option to ignore rendering docs for subcharts.
Example of undesirable behavior:
$ git submodule status
e074e59e9b42fce856b029265d9ccc0163d22f13 charts/subchart2 (2019.0.0-1-ge074e59)
f91a918ebc2ea969bfbcda884c57b7d8f83f45b2 charts/subchart1 (2019.0.2)
$ helm-docs
INFO[2019-08-05T17:55:03-04:00] Found Chart directories [., charts/subchart2, charts/subchart1]
INFO[2019-08-05T17:55:03-04:00] Generating README Documentation for chart charts/subchart1
INFO[2019-08-05T17:55:03-04:00] Generating README Documentation for chart .
INFO[2019-08-05T17:55:03-04:00] Generating README Documentation for chart charts/subchart2
$ git st
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
(commit or discard the untracked or modified content in submodules)
modified: README.md
modified: charts/subchart2 (modified content)
modified: charts/subchart1 (modified content)
no changes added to commit (use "git add" and/or "git commit -a")
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.