Skip to content

Fix subcharts dependencies processing#10174

Closed
vflaux wants to merge 1 commit intohelm:mainfrom
vflaux:fix/10160
Closed

Fix subcharts dependencies processing#10174
vflaux wants to merge 1 commit intohelm:mainfrom
vflaux:fix/10160

Conversation

@vflaux
Copy link
Copy Markdown
Contributor

@vflaux vflaux commented Sep 22, 2021

What this PR does / why we need it:

There is an issue when you use a subchart more than once with alias and that this subchart also have a subchart.

In pkg/chartutil/dependencies.go, getAliasDependency() return a partial copy of the passed chart keeping the same slice for metadata.Dependencies. This results in metadata.Dependencies been shared by multiple Charts objects.
At some point processDependencyEnabled() changes the name of each dependencies by their alias. This impact others dependencies generated by getAliasDependency() and leads to processDependencyEnabled() to not correctly handles their dependencies (as it use the name to do so and the name is now the alias).

This patch make a copy of all the dependencies in a new slice to avoid this issue.

fix #10160

Special notes for your reviewer:

If applicable:

  • this PR contains unit tests
  • this PR has been tested for backwards compatibility

@helm-bot helm-bot added the size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. label Sep 22, 2021
@bacongobbler
Copy link
Copy Markdown
Member

Please provide unit tests to ensure your change fixes the issue. Thanks.

md := *c.Metadata
deps := make([]*chart.Dependency, 0, len(md.Dependencies))
for _, dep := range md.Dependencies {
dep := *dep
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why is this de-referencing the address, then re-assigning a new pointer? Wouldn't a copy be safer?

What happens when you provide a list of nil dependencies? Wouldn't that result in a stack trace when you attempt to de-reference nil? How should this code handle nil dependencies?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

A copy would not give us new Dependency structs.
We need new ones because their name are modified here which leaks on other Charts:

for _, req := range c.Metadata.Dependencies {
if chartDependency := getAliasDependency(c.Dependencies(), req); chartDependency != nil {
chartDependencies = append(chartDependencies, chartDependency)
}
if req.Alias != "" {
req.Name = req.Alias
}
}

When you call getAliasDependency(c.Dependencies(), req) multiple time with the same req.Name, you get new Charts structs each time but their metadata.Dependencies are the same slice which come from the Chart in c.Dependencies() that match the Dependency (req).
Then we iterate over these dependencies (*chart.Chart) and call processDependencyEnabled()

for _, t := range cd {
subpath := path + t.Metadata.Name + "."
if err := processDependencyEnabled(t, cvals, subpath); err != nil {
return err
}
}

At this point the dependencies generated by getAliasDependency are now the pointer c.
Then we iterate over c.Metadata.Dependencies (and call again getAliasDependency) then replace req.Name with req.Alias. But c.Metadata.Dependencies is the slice return by getAliasDependency in the parent, which may be shared with another Chart as seen before.
When the processDependencyEnabled is called with such a Chart (same name but different alias), Dependency structs in c.Metadata.Dependencies have already their name changed to the alias and the following match do not work as expected:
for _, existing := range c.Dependencies() {
for _, req := range c.Metadata.Dependencies {
if existing.Name() == req.Name && IsCompatibleRange(req.Version, existing.Metadata.Version) {
continue Loop

The only Chart dependencies that are kept are the one in c.Dependencies, not in c.Metadata.Dependencies.

With a new slice and new structs for .metadata.Dependencies, the req.Name = req.Alias do not leaks on other Charts.

Not sure if I'm clear enough here, sorry 😕.


Charts.Dependencies are apparently not supposed to contains nil pointers as this line would panic on the req.Name in this case:

for _, existing := range c.Dependencies() {
for _, req := range c.Metadata.Dependencies {
if existing.Name() == req.Name && IsCompatibleRange(req.Version, existing.Metadata.Version) {

But I can add checks for nil if you prefer.

Signed-off-by: Valentin Flaux <vflaux@oui.sncf>
@helm-bot helm-bot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. labels Sep 22, 2021
@vflaux
Copy link
Copy Markdown
Contributor Author

vflaux commented Sep 22, 2021

Just find that there is another PR for the same issue and with the same fix: #9175

dastrobu added a commit to dastrobu/helm that referenced this pull request Dec 8, 2022
imported values are stored in dependency objects, which breaks if a chart dependency is shared among multiple aliases.
By copying the dependency objects in the metadata values can be imported correctly.

Supersedes helm#10174

Signed-off-by: Daniel Strobusch <1847260+dastrobu@users.noreply.github.com>
dastrobu added a commit to dastrobu/helm that referenced this pull request Apr 23, 2025
imported values are stored in dependency objects, which breaks if a chart dependency is shared among multiple aliases.
By copying the dependency objects in the metadata values can be imported correctly.

Supersedes helm#10174

Signed-off-by: Daniel Strobusch <1847260+dastrobu@users.noreply.github.com>
dastrobu added a commit to dastrobu/helm that referenced this pull request Apr 23, 2025
imported values are stored in dependency objects, which breaks if a chart dependency is shared among multiple aliases.
By copying the dependency objects in the metadata values can be imported correctly.

Supersedes helm#10174

Signed-off-by: Daniel Strobusch <1847260+dastrobu@users.noreply.github.com>
dastrobu added a commit to dastrobu/helm that referenced this pull request Apr 23, 2025
imported values are stored in dependency objects, which breaks if a chart dependency is shared among multiple aliases.
By copying the dependency objects in the metadata values can be imported correctly.

Supersedes helm#10174

Signed-off-by: Daniel Strobusch <1847260+dastrobu@users.noreply.github.com>
dastrobu added a commit to dastrobu/helm that referenced this pull request Apr 25, 2025
imported values are stored in dependency objects, which breaks if a chart dependency is shared among multiple aliases.
By copying the dependency objects in the metadata values can be imported correctly.

Supersedes helm#10174

Signed-off-by: Daniel Strobusch <1847260+dastrobu@users.noreply.github.com>
dastrobu added a commit to dastrobu/helm that referenced this pull request Apr 25, 2025
imported values are stored in dependency objects, which breaks if a chart dependency is shared among multiple aliases.
By copying the dependency objects in the metadata values can be imported correctly.

Supersedes helm#10174

Signed-off-by: Daniel Strobusch <1847260+dastrobu@users.noreply.github.com>
chrko pushed a commit to servicelayers/helm that referenced this pull request Jun 24, 2025
imported values are stored in dependency objects, which breaks if a chart dependency is shared among multiple aliases.
By copying the dependency objects in the metadata values can be imported correctly.

Supersedes helm#10174

Signed-off-by: Daniel Strobusch <1847260+dastrobu@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown

This pull request has been marked as stale because it has been open for 90 days with no activity. This pull request will be automatically closed in 30 days if no further activity occurs.

@github-actions github-actions bot added the Stale label Aug 26, 2025
@github-actions github-actions bot closed this Sep 27, 2025
Shaps pushed a commit to Shaps/helm that referenced this pull request Sep 27, 2025
imported values are stored in dependency objects, which breaks if a chart dependency is shared among multiple aliases.
By copying the dependency objects in the metadata values can be imported correctly.

Supersedes helm#10174

Signed-off-by: Daniel Strobusch <1847260+dastrobu@users.noreply.github.com>
chrko pushed a commit to servicelayers/helm that referenced this pull request Sep 30, 2025
imported values are stored in dependency objects, which breaks if a chart dependency is shared among multiple aliases.
By copying the dependency objects in the metadata values can be imported correctly.

Supersedes helm#10174

Signed-off-by: Daniel Strobusch <1847260+dastrobu@users.noreply.github.com>
chrko pushed a commit to servicelayers/helm that referenced this pull request Nov 12, 2025
imported values are stored in dependency objects, which breaks if a chart dependency is shared among multiple aliases.
By copying the dependency objects in the metadata values can be imported correctly.

Supersedes helm#10174

Signed-off-by: Daniel Strobusch <1847260+dastrobu@users.noreply.github.com>
chrko pushed a commit to servicelayers/helm that referenced this pull request Dec 9, 2025
imported values are stored in dependency objects, which breaks if a chart dependency is shared among multiple aliases.
By copying the dependency objects in the metadata values can be imported correctly.

Supersedes helm#10174

Signed-off-by: Daniel Strobusch <1847260+dastrobu@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M Denotes a PR that changes 30-99 lines, ignoring generated files. Stale

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 3.7.0 - Helm generates an incorrect chart tree in some cases

3 participants