Added seed code for caas-helm.
[ta/caas-helm.git] / src / chart-repo-handler / pkg / repo / index.go
1 // Copyright 2019 Nokia
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // tonyaw: refer to "kubernetes/helm/pkg/repo/index.go"
16 package repo
17
18 import (
19         "path/filepath"
20         "strings"
21         "time"
22
23         "github.com/ghodss/yaml"
24
25         // tonyaw: added import
26         "log"
27         "pkg/chartutil"
28
29         "github.com/ncw/swift"
30         "k8s.io/helm/pkg/provenance"
31         helm_repo "k8s.io/helm/pkg/repo"
32         "k8s.io/helm/pkg/urlutil"
33 )
34
35 //var IndexPath = "index.yaml"
36
37 // LoadIndexFile takes a file at the given path and returns an IndexFile object
38 func LoadIndexFile(c *swift.Connection, container string, path string) (*IndexFile, error) {
39         // TBD.tonyaw: didin't tested it
40         b, err := c.ObjectGetBytes(container, path)
41         if err != nil {
42                 return nil, err
43         }
44         return loadIndex(b)
45 }
46
47 // tonyaw: return "IndexFile" defined in this file.
48 func NewIndexFile() *IndexFile {
49         var indexFile *helm_repo.IndexFile
50
51         indexFile = &helm_repo.IndexFile{
52                 APIVersion: helm_repo.APIVersionV1,
53                 Generated:  time.Now(),
54                 Entries:    map[string]helm_repo.ChartVersions{},
55                 PublicKeys: []string{},
56         }
57
58         return &IndexFile{
59                 IndexFile: indexFile,
60         }
61 }
62
63 // IndexFile represents the index file in a chart repository
64 // tonyaw: here only add "WriteObject" function.
65 type IndexFile struct {
66         *helm_repo.IndexFile
67 }
68
69 // WriteObject writes an index file to the given destination path.
70 func (i IndexFile) WriteObject(c *swift.Connection, container, path string) error {
71         b, err := yaml.Marshal(i)
72         if err != nil {
73                 return err
74         }
75
76         // tonyaw: if "index" exists, this step will overwrite it.
77         return c.ObjectPutBytes(container, path, b, "text/plain")
78 }
79
80 // tonyaw: Merge "IndexFile" defined in this file.
81 func (i *IndexFile) Merge(f *IndexFile) {
82         for _, cvs := range f.Entries {
83                 for _, cv := range cvs {
84                         if !i.Has(cv.Name, cv.Version) {
85                                 e := i.Entries[cv.Name]
86                                 i.Entries[cv.Name] = append(e, cv)
87                         }
88                 }
89         }
90 }
91
92 // IndexDirectory reads a (flat) directory and generates an index.
93 //
94 // It indexes only charts that have been packaged (*.tgz).
95 //
96 // The index returned will be in an unsorted state
97 func IndexDirectory(c *swift.Connection, container, baseURL, rootPath, indexName string) (*IndexFile, error) {
98         // tonyaw: Usw Swift command to replace FileSystem calls
99         objects, err := c.ObjectNames(container, nil)
100
101         if err != nil {
102                 return nil, err
103         }
104         index := NewIndexFile()
105         for _, object := range objects {
106                 if !strings.HasPrefix(object, rootPath) {
107                         continue
108                 }
109                 if object == filepath.Join(rootPath, indexName) {
110                         //log.Println("Ignore", filepath.Join(rootPath, indexName))
111                         continue
112                 }
113                 if !strings.HasSuffix(object, ".tgz") {
114                         log.Println("Ignore", object)
115                         continue
116                 }
117
118                 //fname := filepath.Base(object)
119                 chartData, err := chartutil.Load(c, container, object)
120                 if err != nil {
121                         log.Println("Error with object:", object, ",", err)
122                         continue
123                 }
124                 //huszty: open the object here for sha256 calculation
125                 objectReader, _, err := c.ObjectOpen(container, object, false, nil)
126                 //hash, err := provenance.DigestFile(object)
127                 hash, err := provenance.Digest(objectReader)
128                 if err != nil {
129                         return index, err
130                 }
131                 log.Println("Added:", object)
132                 //huszty: index.Add would split the path from the object if url is provided
133                 //so join the url with the prefixed object path to fake subdirectories correctly
134                 objectPath, _ := urlutil.URLJoin(baseURL, object)
135                 index.Add(chartData.Metadata, objectPath, "", hash)
136                 objectReader.Close()
137         }
138         return index, nil
139 }
140
141 // loadIndex loads an index file and does minimal validity checking.
142 //
143 // This will fail if API Version is not set (ErrNoAPIVersion) or if the unmarshal fails.
144 func loadIndex(data []byte) (*IndexFile, error) {
145         i := &IndexFile{}
146         if err := yaml.Unmarshal(data, i); err != nil {
147                 return i, err
148         }
149
150         return i, nil
151 }
152
153 // tonyaw: refer to "index" from "helm/cmd/helm/repo_index.go".
154 func Index(c *swift.Connection, container, url, rootPath, indexName string) error {
155         i, err := IndexDirectory(c, container, url, rootPath, indexName)
156         if err != nil {
157                 return err
158         }
159         i.SortEntries()
160         return i.WriteObject(c, container, filepath.Join(rootPath, indexName))
161 }