Skip to content

Add include-file flag for external files #8841

Closed
hunsche wants to merge 3 commits intohelm:mainfrom
hunsche:add-include-file
Closed

Add include-file flag for external files #8841
hunsche wants to merge 3 commits intohelm:mainfrom
hunsche:add-include-file

Conversation

@hunsche
Copy link

@hunsche hunsche commented Oct 2, 2020

This PR implements the --include-file and --include-dir flags for the install, upgrade and template commands.

These flags load local files and make them available to the chart, so they can be used in templates with functions like .Files.Get or .Files.Glob.

This is my first PR here, and I would appreciate comments regarding style, code split (what goes where), and the amount and quality of tests that we need.

Thank you!

Parsing

Both flags are arrays and can have multiple values, either comma-separated, or by writing the flag multiple times.

Both flags require a key and a path. They will get parsed just like --set*, and later values will overwrite previous ones. The paths are then added as if they are part of the chart; the keys represent the file names inside the chart.

You can use both flags in the same command. Files are parsed first, then directories.

Single files

helm template test . --include-file my_license.conf=../license.conf,foo=foo.txt --include-file bar=bar.txt --set license=my_license.conf

# in chart/templates/cmap.yml
{{ (.Files.Glob .Values.license).AsConfig | indent 2 }}

Dirs

The include-dir flag can include all the files from a local directory. It will not recurse in subdirectories.

helm template test . --include-dir certs=../certs

# in chart/templates/cmap.yml
{{ (.Files.Glob "certs/").AsConfig | indent 2 }}

Globs

The --include-dir flag optionally supports a glob. It can recurse, but it will take everything it finds and add it under one folder, specified in the key.

helm template test . --include-dir conf=../prod/conf/*.conf

# in chart/templates/cmap.yml
{{ (.Files.Glob "conf/").AsConfig | indent 2 }}

Closing

closes #3276
closes #8227

Feedback is welcomed! I know there has been a lot of interest for this issue, so I am looking forward for your input.
If you don't know where to start, here are the open issues with this PR:

  • currently, files are parsed first, then dirs; if a file overlaps somehow, the dir will overwrite it. What if we parse files last, so you can potentially overwrite an unwanted file in a dir? This one is easy to do
  • if a path is not found, is unreadable, or if a glob yields no files, the helm command currently fails. Should we continue the install with a warning?
  • all external files are added to the root of the chart. This means you can overwrite any chart file, including any template. Should we add these files to a special _external dir? Chart authors will need to append it to every lookup: {{ (.Files.Glob "_external/certs/") }}

This PR is a continuation of the PR #8227 created by @vladfr

Still todo:

  • implement --include-dir to get all files in a dir; this could be enhanced with glob
  • add tests

@helm-bot helm-bot added the size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. label Oct 2, 2020
Signed-off-by: Matheus Hunsche <matheus.hunsche@ifood.com.br>
Signed-off-by: Matheus Hunsche <matheus.hunsche@ifood.com.br>
@hunsche
Copy link
Author

hunsche commented Oct 2, 2020

@mattfarina did the update with the master and corrected the changes, I would like feedback.

@hunsche hunsche marked this pull request as draft October 16, 2020 15:30
@hunsche hunsche marked this pull request as ready for review October 16, 2020 15:31
@mattfarina mattfarina added this to the 3.5.0 milestone Oct 19, 2020
@vladfr
Copy link

vladfr commented Oct 26, 2020

@hunsche = lifesaver! Thank you sir.

Thanks for keeping the original pr text, there are some issues still to do, as described there. @hunsche Thoughts around the open issues?

@hunsche
Copy link
Author

hunsche commented Oct 28, 2020

Hello @vladfr, I would like to discuss these topics.

About these two items:

  • currently, files are parsed first, then dirs; if a file overlaps somehow, the dir will overwrite it. What if we parse files last, so you can potentially overwrite an unwanted file in a dir? This one is easy to do
  • all external files are added to the root of the chart. This means you can overwrite any chart file, including any template. Should we add these files to a special _external dir? Chart authors will need to append it to every lookup: {{ (.Files.Glob "_external/certs/") }}

I think it is the responsibility of the graphic developer to understand the overlap of the files, but if it is necessary to generate a warning or validation it is relatively simple.

About this item:

  • if a path is not found, is unreadable, or if a glob yields no files, the helm command currently fails. Should we continue the install with a warning?

I really like the idea of ​​not failing, but a warning may be necessary.

@andresbott
Copy link

Hello,
I'm currently directly looking into this PR as it solves one of our biggest problems.
I tried the PR locally and it works for our use-case; I'm looking forward to get this merged.
Please let me know if i can help.

my feedback to the current questions:

currently, files are parsed first, then dirs; if a file overlaps somehow, the dir will overwrite it. What if we parse files last, so you can potentially overwrite an unwanted file in a dir? This one is easy to do

No strong feeling here, it might make sense to allow files to be more specific that globs;
I plan to use this with grafana dashboards, here could see some value by being able to do:
--include-dir gf-dashboards/*.json --include-file patched-dashboard.json

if a path is not found, is unreadable, or if a glob yields no files, the helm command currently fails. Should we continue the install with a warning?

Initially i was thinking that failing is the better solution but on a second thought it might be better to not fail; If we think again about the grafana dashboards example, I also would like to deploy grafana with my CICD even if no dashboard matches the glob.

all external files are added to the root of the chart. This means you can overwrite any chart file, including any template. Should we add these files to a special _external dir? Chart authors will need to append it to every lookup: {{ (.Files.Glob "_external/certs/") }}

No strong feeling here either, I would argue that its up to the user to avoid the conflicts and not rely on an "_external" structure

@himmakam
Copy link

himmakam commented Nov 9, 2020

Hi, any updates on this please. I am eagerly waiting for this PR to be merged so that I can use it in my implementation.

@vio-f
Copy link

vio-f commented Nov 11, 2020

would be nice to have this soon

@andresbott
Copy link

From my view at the moment the uncertainty is around some of the open topics and a decision needs to be done;
or was it already decided to go forward with the current status?

@hunsche, @mattfarina any advice on who can take a decision around those points?
I'm new to the helm contribution model, I checked the documentation but it's still no clear who can or will review PRs.

I had a quick look and code-wise any of the three mentioned points seem to be easy to solve.

For what it's worth, I migrated a chart to use the forked branch and have this working correctly

@bacongobbler
Copy link
Member

any advice on who can take a decision around those points?

Have a look at the Contributing Guide, specifically the section on PR lifecycles. Anyone from the OWNERS file can review and approve this PR.

At the moment, we've been focused and more concerned about the Helm 2 deprecation plan that was scheduled for last week. Now that milestone is behind us, we can re-focus on reviewing PRs like this one.

Thanks for your patience.

@andresbott
Copy link

@bacongobbler thanks for the clarification, I checked the contributing guidelines, but it was not clear for me who can review.

Let me know if i can help on this one.

@himmakam
Copy link

Any update on this please. Could someone please review and merge this PR so that we can use it.

@hunsche
Copy link
Author

hunsche commented Nov 25, 2020

From my view at the moment the uncertainty is around some of the open topics and a decision needs to be done;
or was it already decided to go forward with the current status?

@hunsche, @mattfarina any advice on who can take a decision around those points?
I'm new to the helm contribution model, I checked the documentation but it's still no clear who can or will review PRs.

I had a quick look and code-wise any of the three mentioned points seem to be easy to solve.

For what it's worth, I migrated a chart to use the forked branch and have this working correctly

I believe we can follow, with these points as is, and collect feedback for improvements in new versions.

@thomastvedt
Copy link

I just spent 6 hours trying various workarounds, and then I found this which would solve all my problems 🥰
I'm really looking forward to this getting merged! And it seems ready to go too? Great work @hunsche 😉
Ready to hit the merge button @bacongobbler ? 🚀

@technosophos
Copy link
Member

How do rollbacks work in this scenario?

Say I do the following:

  1. helm install --include-dir=foo/bar myrelease somechart (Creates myrelease.v1)
  2. helm upgrade myrelease (Creates myrelease.v2)
  3. helm rollback myrelease (Rolls back to myrelease.v1)`

In step 3, Helm may attempt to re-render resources. Does it still have access to the content of --include-dir? Where are those files located in the release record?

@sbose78
Copy link
Contributor

sbose78 commented Dec 18, 2020

Thank you @hunsche for this feature contribution.

I've gone through the discussion in #3276 :)

I typically handle this use case by

  1. Having tooling which creates secrets/configmaps
  2. Have a way to reference them in my values.yaml

Would the included files be treated as values which happen to be rendered from Go templates, conceptually ?

The reason I bring this up in the PR is that:

  • if we are treating the files in --include-file as a special kind of "values", we should treat them that way and not worry about re-rendering on rollback.
  • If we treat them as an extension of the content in /templates , then re-rendering on rollback is a possibility we need to consider.

@mattfarina mattfarina modified the milestones: 3.5.0, 3.6.0 Jan 5, 2021
@mattfarina
Copy link
Collaborator

I'm sorry that we were not able to get to this prior to preparing to release v3.5.0. We are moving into the release candidate phase so this will need to be looked at for 3.6.

@planetf1
Copy link

I was just researching how to do this with helm - these flags look just what I need

Copy link
Member

@technosophos technosophos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pulling this off of 3.6.0 because no rollback solution was ever explained/implemented. I am adding a block on this PR so that commenters understand that this PR will not be merged until the rollback scenario is solved. Otherwise, rollback would be dangerous and unpredictable.

@torblerone
Copy link

Is there an ETA when this will be done? It is painful currently having to rely on symlinks instead of this feature.

@hunsche
Copy link
Author

hunsche commented Jun 14, 2021

I'm striving for the next version.

@itaispiegel
Copy link

Hey, just wanted to mention that our team is really looking forward for this feature.
We currently have some ugly patches in our code and this could solve them beautifully.
Hope this gets released soon :)

@itaispiegel
Copy link

Just want to update that we talked about this feature at the Helm dev call, and decided that we need to write documentation and tests for the expected behaviour of these flags :)

@duyleekun
Copy link

Usually helm charts are self documented (as in what can be config) by looking at the values.yaml file. Would merging this make this the first time we break this rule (do we even have this rule?)?

Anyway, updating Chart.yaml schema and perform file/flag validation would make my concern above less of an issue. Could even make this play well with rancher or some other software that install chart by UI.

I still think some use cases could be resolved without this PR by using kubectl create secret. Could not cover all use cases though. Not really urgent merge IMO.

  # Create a new secret named my-secret with keys for each file in folder bar
  kubectl create secret generic my-secret --from-file=path/to/bar
  
  # Create a new secret named my-secret with specified keys instead of names on disk
  kubectl create secret generic my-secret --from-file=ssh-privatekey=path/to/id_rsa
--from-file=ssh-publickey=path/to/id_rsa.pub
  
  # Create a new secret named my-secret with key1=supersecret and key2=topsecret
  kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret
  
  # Create a new secret named my-secret using a combination of a file and a literal
  kubectl create secret generic my-secret --from-file=ssh-privatekey=path/to/id_rsa --from-literal=passphrase=topsecret
  
  # Create a new secret named my-secret from an env file
  kubectl create secret generic my-secret --from-env-file=path/to/bar.env

@itaispiegel
Copy link

itaispiegel commented Aug 20, 2021

@duyleekun In the case of my team, your suggestion couldn't solve our use case. We have a Helm chart for the application we're developing, and we provide the app's configurations with it. Then, when you install the chart, you install with the command: helm install <release-name> <chart-name> --set env=staging, and it'll deploy the app with its staging configurations.
Because of this use case, we have the configurations duplicated - once for the local development of the app (can run without K8s or even without Docker), and the second is inside our chart's directory.

Hope it's clear :)

@duyleekun
Copy link

I think you could use --set envSecrets[0]=secret-name-for-staging, similar to the imagePullSecrets we had for ages. Just my idea.

I still think this could create a lot of potentials to chart developer, I wouldn't mind if we can make this friendlier to user along the way

@itaispiegel
Copy link

@duyleekun I understand what you're suggesting, and we've thought about it for quite some time, but it's not as convenient because then we need to remember to update the configurations on each deployment, instead of just installing the chart.
This feature could really help us and I think it could help more users.

@itaispiegel
Copy link

Btw, I've thought about it more, and I think this feature could be improved by a few simple additions that I'd like to discuss with you.
First of all, when installing a chart accessing external files, the current behavior is that it returns nothing. I think this is a bit unexpected, and that it should either fail or print a warning telling the user to pass the added flags.
The second suggestion is that we could also add the flags to helm package, and it'll make the packaged chart include the files that were present at the time. It'll then make the "external files" known only to the developers and the user installing the chart shouldn't even care that that chart includes files that didn't arrive from the chart's working directory.

What do you think about these additions? I'd be glad to hear your opinions on them :)

@duyleekun
Copy link

First of all, when installing a chart accessing external files, the current behavior is that it returns nothing. I think this is a bit unexpected, and that it should either fail or print a warning telling the user to pass the added flags.

I agree with your idea about fail or warn, as I noted above, it should be document officially in the schema or someplace. I'm a bit skeptical while reading README.md of any helm chart, I usually read non template file to see what the chart expect from me.

The second suggestion is that we could also add the flags to helm package, and it'll make the packaged chart include the files that were present at the time. It'll then make the "external files" known only to the developers and the user installing the chart shouldn't even care that that chart includes files that didn't arrive from the chart's working directory.

I thought this was implemented in the current release by putting files in the template folder, I could be wrong though. I guess your idea is to provide sensible default file embedded in the chart so user can replace whatever file they want later. IMO, this kind of make sense because I expect charts to be functional OOB and they usually do. I don't really have many use cases in mind yet for this suggestion yet, will certainly throw more idea later.

@itaispiegel
Copy link

@duyleekun I read the code in this PR and it seems that when you run helm package, the packaged chart will have {{ .Files.Get ~/my_file }}.
I'm planning to start working on this soon (depending on my personal schedule) and hopefully I'll open a PR for these additions soon :)

@SimplyAmuthan
Copy link

Hi, any updates on this please.... looking forward to this feature...

@itaispiegel
Copy link

Hi, any updates on this please.... looking forward to this feature...

I know.. I wish I could still work on this, but unfortunately I can't continue working on this soon.
You're welcome to continue my work here if you can :)

@huytran1ibm
Copy link

Hi, any updates on this please.... looking forward to this feature...

I know.. I wish I could still work on this, but unfortunately I can't continue working on this soon. You're welcome to continue my work here if you can :)

what else needs to be done to get this completed?

@bricss
Copy link

bricss commented Aug 29, 2022

Can we get it shipped somehow? 😃 Badly needed for monorepo(s) 🙄

@PauloFerreira25
Copy link

PauloFerreira25 commented Oct 18, 2022

@technosophos
About rollback.
The end result is a yaml equal to the build if it's embedded in the values.
The implementation is not making a reference to a directory, it only allows access to a directory outside the chart.

My doubt is, why is this allowed:

helm install --values /tmp/some-external-values.yaml myrelease somechart

Where /tmp/some-external-values.yaml is

externalConf: |-
   totalExternalFile
---
apiVersion: v1
kind: ConfigMap
metadata:
   name: "RELEASE-NAME-"
date:
   external.conf: |-
{{ .Values.externalConf }}

And generate file:

---
# Source: configmap/templates/config-map.yaml
apiVersion: v1
kind: ConfigMap
metadata:
   name: "RELEASE-NAME-"
date:
   external.conf: |-
      totalExternalFile

And accessing another directory outside the chart is not allowed?

The end result will be the same format as yaml

The whole community waits for this.
Please stop blocking this functionality

@itaispiegel
Copy link

itaispiegel commented Oct 18, 2022 via email

@joejulian
Copy link
Contributor

Since @hunsche hasn't been able to work on this for a very long time and @itaispiegel picked it back up with #10077, I'm closing this PR in favor of that one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow helm to add external files to chart deployment