Repository: helm/helm (go)

Issue:
Feature: Add annotations field to the index.yaml file
Systems may want to add metadata to an index.yaml file. This feature would be to add an `annotations` top level field, similar to the one in `Chart.yaml` that can be used to add extra information.

Pull request description:
Adding annotation to index.yaml file
Chart.yaml files have an annotation field that allow a chart to
have custom information similar to the way Kubernetes annotations
work.

In an index.yaml file each chart version can have annotations in
a similar manner to the Chart.yaml file. It is derived from the
same underlying struct.

These enable extension points where people can add their own info.

One thing missing is the ability to extend the top level of an
index file. This change adds annotations to the top level of an
index.yaml file. This would provide top level support for vendors
to extent index.yaml files.

Closes #8767 

**What this PR does / why we need it**:

Vendors have started to extend index.yaml files with their own metadata. This provides top level support in index.yaml files

**If applicable**:
- [ ] this PR contains documentation
- [x] this PR contains unit tests
- [x] this PR has been tested for backwards compatibility


Patch:
diff --git a/pkg/repo/index.go b/pkg/repo/index.go
index 55b984eea..43f1e1c87 100644
--- a/pkg/repo/index.go
+++ b/pkg/repo/index.go
@@ -83,6 +83,10 @@ type IndexFile struct {
 	Generated  time.Time                `json:"generated"`
 	Entries    map[string]ChartVersions `json:"entries"`
 	PublicKeys []string                 `json:"publicKeys,omitempty"`
+
+	// Annotations are additional mappings uninterpreted by Helm. They are made available for
+	// other applications to add information to the index file.
+	Annotations map[string]string `json:"annotations,omitempty"`
 }
 
 // NewIndexFile initializes an index.


Test patch:
diff --git a/pkg/repo/index_test.go b/pkg/repo/index_test.go
index c22588971..00135f97c 100644
--- a/pkg/repo/index_test.go
+++ b/pkg/repo/index_test.go
@@ -36,6 +36,7 @@ import (
 
 const (
 	testfile            = "testdata/local-index.yaml"
+	annotationstestfile = "testdata/local-index-annotations.yaml"
 	chartmuseumtestfile = "testdata/chartmuseum-index.yaml"
 	unorderedTestfile   = "testdata/local-index-unordered.yaml"
 	testRepo            = "test-repo"
@@ -153,6 +154,21 @@ func TestLoadIndexFile(t *testing.T) {
 	verifyLocalIndex(t, i)
 }
 
+func TestLoadIndexFileAnnotations(t *testing.T) {
+	i, err := LoadIndexFile(annotationstestfile)
+	if err != nil {
+		t.Fatal(err)
+	}
+	verifyLocalIndex(t, i)
+
+	if len(i.Annotations) != 1 {
+		t.Fatalf("Expected 1 annotation but got %d", len(i.Annotations))
+	}
+	if i.Annotations["helm.sh/test"] != "foo bar" {
+		t.Error("Did not get expected value for helm.sh/test annotation")
+	}
+}
+
 func TestLoadUnorderedIndex(t *testing.T) {
 	b, err := ioutil.ReadFile(unorderedTestfile)
 	if err != nil {
diff --git a/pkg/repo/testdata/local-index-annotations.yaml b/pkg/repo/testdata/local-index-annotations.yaml
new file mode 100644
index 000000000..ffaaa15aa
--- /dev/null
+++ b/pkg/repo/testdata/local-index-annotations.yaml
@@ -0,0 +1,50 @@
+apiVersion: v1
+entries:
+  nginx:
+    - urls:
+        - https://kubernetes-charts.storage.googleapis.com/nginx-0.2.0.tgz
+      name: nginx
+      description: string
+      version: 0.2.0
+      home: https://github.com/something/else
+      digest: "sha256:1234567890abcdef"
+      keywords:
+        - popular
+        - web server
+        - proxy
+    - urls:
+        - https://kubernetes-charts.storage.googleapis.com/nginx-0.1.0.tgz
+      name: nginx
+      description: string
+      version: 0.1.0
+      home: https://github.com/something
+      digest: "sha256:1234567890abcdef"
+      keywords:
+        - popular
+        - web server
+        - proxy
+  alpine:
+    - urls:
+        - https://kubernetes-charts.storage.googleapis.com/alpine-1.0.0.tgz
+        - http://storage2.googleapis.com/kubernetes-charts/alpine-1.0.0.tgz
+      name: alpine
+      description: string
+      version: 1.0.0
+      home: https://github.com/something
+      keywords:
+        - linux
+        - alpine
+        - small
+        - sumtin
+      digest: "sha256:1234567890abcdef"
+  chartWithNoURL:
+    - name: chartWithNoURL
+      description: string
+      version: 1.0.0
+      home: https://github.com/something
+      keywords:
+        - small
+        - sumtin
+      digest: "sha256:1234567890abcdef"
+annotations:
+  helm.sh/test: foo bar