Commit 7dd6eb22 authored by Taylor Thomas's avatar Taylor Thomas Committed by GitHub

Merge pull request #2486 from sushilkm/issues/2383

Adds alias for dependencies
parents e45d93fb 351dfea5
...@@ -229,6 +229,38 @@ Managing charts with `requirements.yaml` is a good way to easily keep ...@@ -229,6 +229,38 @@ Managing charts with `requirements.yaml` is a good way to easily keep
charts updated, and also share requirements information throughout a charts updated, and also share requirements information throughout a
team. team.
#### Alias field in requirements.yaml
In addition to the other fields above, each requirements entry may contain
the optional field `alias`.
Adding an alias for a dependency chart would add another copy
of the chart as a new depdendency using alias as name of new dependency.
One can use `alias` in cases where they need multiple copies of same chart
as dependencies all independent of one another.
````
# parentchart/requirements.yaml
dependencies:
- name: subchart
repository: http://localhost:10191
version: 0.1.0
alias:
- one-more-subchart
- another-subchart
````
In the above example we will get 3 depenendencies in all for `parentchart`
```
subchart
one-more-subchart
another-subchart
```
Manual way of achieving this is copy/pasting same chart in
`charts/` directory multiple times with different name.
#### Tags and Condition fields in requirements.yaml #### Tags and Condition fields in requirements.yaml
In addition to the other fields above, each requirements entry may contain In addition to the other fields above, each requirements entry may contain
......
...@@ -65,6 +65,8 @@ type Dependency struct { ...@@ -65,6 +65,8 @@ type Dependency struct {
// ImportValues holds the mapping of source values to parent key to be imported. Each item can be a // ImportValues holds the mapping of source values to parent key to be imported. Each item can be a
// string or pair of child/parent sublist items. // string or pair of child/parent sublist items.
ImportValues []interface{} `json:"import-values"` ImportValues []interface{} `json:"import-values"`
// Alias usable alias to be used for the chart
Alias []string `json:"alias"`
} }
// ErrNoRequirementsFile to detect error condition // ErrNoRequirementsFile to detect error condition
...@@ -216,6 +218,28 @@ func ProcessRequirementsTags(reqs *Requirements, cvals Values) { ...@@ -216,6 +218,28 @@ func ProcessRequirementsTags(reqs *Requirements, cvals Values) {
} }
func copyChartAsAlias(charts []*chart.Chart, dependentChart, aliasChart string) *chart.Chart {
var chartFound chart.Chart
for _, existingChart := range charts {
if existingChart == nil {
continue
}
if existingChart.Metadata == nil {
continue
}
if existingChart.Metadata.Name != dependentChart {
continue
}
chartFound = *existingChart
newMetadata := *existingChart.Metadata
newMetadata.Name = aliasChart
chartFound.Metadata = &newMetadata
return &chartFound
}
return nil
}
// ProcessRequirementsEnabled removes disabled charts from dependencies // ProcessRequirementsEnabled removes disabled charts from dependencies
func ProcessRequirementsEnabled(c *chart.Chart, v *chart.Config) error { func ProcessRequirementsEnabled(c *chart.Chart, v *chart.Config) error {
reqs, err := LoadRequirements(c) reqs, err := LoadRequirements(c)
...@@ -228,6 +252,21 @@ func ProcessRequirementsEnabled(c *chart.Chart, v *chart.Config) error { ...@@ -228,6 +252,21 @@ func ProcessRequirementsEnabled(c *chart.Chart, v *chart.Config) error {
// no requirements to process // no requirements to process
return nil return nil
} }
for _, req := range reqs.Dependencies {
for _, alias := range req.Alias {
aliasDependency := copyChartAsAlias(c.Dependencies, req.Name, alias)
if aliasDependency == nil {
break
}
c.Dependencies = append(c.Dependencies, aliasDependency)
origReqName := req.Name
req.Name = alias
reqs.Dependencies = append(reqs.Dependencies, req)
req.Name = origReqName
}
}
// set all to true // set all to true
for _, lr := range reqs.Dependencies { for _, lr := range reqs.Dependencies {
lr.Enabled = true lr.Enabled = true
......
...@@ -320,3 +320,59 @@ func verifyRequirementsImportValues(t *testing.T, c *chart.Chart, v *chart.Confi ...@@ -320,3 +320,59 @@ func verifyRequirementsImportValues(t *testing.T, c *chart.Chart, v *chart.Confi
} }
} }
func TestCopyChartAsAlias(t *testing.T) {
c, err := Load("testdata/frobnitz")
if err != nil {
t.Fatalf("Failed to load testdata: %s", err)
}
if aliasChart := copyChartAsAlias(c.Dependencies, "mariners", "another-mariner"); aliasChart != nil {
t.Fatalf("expected no chart but got %s", aliasChart.Metadata.Name)
}
aliasChart := copyChartAsAlias(c.Dependencies, "mariner", "another-mariner")
if aliasChart == nil {
t.Fatal("Failed to find dependent chart")
}
if aliasChart.Metadata.Name != "another-mariner" {
t.Fatal(`Failed to update chart-name for alias "dependent chart`)
}
}
func TestDependentChartAliases(t *testing.T) {
c, err := Load("testdata/dependent-chart-alias")
if err != nil {
t.Fatalf("Failed to load testdata: %s", err)
}
if len(c.Dependencies) == 0 {
t.Fatal("There are no dependencies to run this test")
}
origLength := len(c.Dependencies)
if err := ProcessRequirementsEnabled(c, c.Values); err != nil {
t.Fatalf("Expected no errors but got %q", err)
}
if len(c.Dependencies) == origLength {
t.Fatal("Expected alias dependencies to be added, but did not got that")
}
reqmts, err := LoadRequirements(c)
if err != nil {
t.Fatalf("Cannot load requirements for test chart, %v", err)
}
var expectedDependencyCharts int
for _, reqmt := range reqmts.Dependencies {
expectedDependencyCharts++
if len(reqmt.Alias) >= 0 {
expectedDependencyCharts += len(reqmt.Alias)
}
}
if len(c.Dependencies) != expectedDependencyCharts {
t.Fatalf("Expected number of chart dependencies %d, but got %d", expectedDependencyCharts, len(c.Dependencies))
}
}
apiVersion: v1
name: frobnitz
description: This is a frobnitz.
version: "1.2.3"
keywords:
- frobnitz
- sprocket
- dodad
maintainers:
- name: The Helm Team
email: helm@example.com
- name: Someone Else
email: nobody@example.com
sources:
- https://example.com/foo/bar
home: http://example.com
icon: https://example.com/64x64.png
This is an install document. The client may display this.
# Frobnitz
This is an example chart.
## Usage
This is an example. It has no usage.
## Development
For developer info, see the top-level repository.
This should be ignored by the loader, but may be included in a chart.
name: alpine
description: Deploy a basic Alpine Linux pod
version: 0.1.0
home: https://k8s.io/helm
This example was generated using the command `helm create alpine`.
The `templates/` directory contains a very simple pod resource with a
couple of parameters.
The `values.toml` file contains the default values for the
`alpine-pod.yaml` template.
You can install this example using `helm install docs/examples/alpine`.
name: mast1
description: A Helm chart for Kubernetes
version: 0.1.0
home: ""
# Default values for mast1.
# This is a YAML-formatted file.
# Declare name/value pairs to be passed into your templates.
# name = "value"
apiVersion: v1
kind: Pod
metadata:
name: {{.Release.Name}}-{{.Chart.Name}}
labels:
heritage: {{.Release.Service}}
chartName: {{.Chart.Name}}
chartVersion: {{.Chart.Version | quote}}
annotations:
"helm.sh/created": "{{.Release.Time.Seconds}}"
spec:
restartPolicy: {{default "Never" .restart_policy}}
containers:
- name: waiter
image: "alpine:3.3"
command: ["/bin/sleep","9000"]
<?xml version="1.0"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.0" width="256" height="256" id="test">
<desc>Example icon</desc>
<rect id="first" x="2" y="2" width="40" height="60" fill="navy"/>
<rect id="second" x="15" y="4" width="40" height="60" fill="red"/>
</svg>
dependencies:
- name: alpine
version: "0.1.0"
repository: https://example.com/charts
- name: mariner
version: "4.3.2"
repository: https://example.com/charts
digest: invalid
dependencies:
- name: alpine
version: "0.1.0"
repository: https://example.com/charts
- name: mariner
version: "4.3.2"
repository: https://example.com/charts
alias:
- mariners1
- mariners2
# A values file contains configuration.
name: "Some Name"
section:
name: "Name in a section"
...@@ -146,7 +146,7 @@ func TestResolve(t *testing.T) { ...@@ -146,7 +146,7 @@ func TestResolve(t *testing.T) {
} }
func TestHashReq(t *testing.T) { func TestHashReq(t *testing.T) {
expect := "sha256:1feffe2016ca113f64159d91c1f77d6a83bcd23510b171d9264741bf9d63f741" expect := "sha256:917e251ddba291096889f81eb7de713ab4e1afbbb07c576dfd7d66ba9300b12b"
req := &chartutil.Requirements{ req := &chartutil.Requirements{
Dependencies: []*chartutil.Dependency{ Dependencies: []*chartutil.Dependency{
{Name: "alpine", Version: "0.1.0", Repository: "http://localhost:8879/charts"}, {Name: "alpine", Version: "0.1.0", Repository: "http://localhost:8879/charts"},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment