github.com/lrills/helm@v2.8.1+incompatible/pkg/repo/local.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors All rights reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package repo 18 19 import ( 20 "fmt" 21 htemplate "html/template" 22 "io/ioutil" 23 "net/http" 24 "path/filepath" 25 "strings" 26 27 "github.com/ghodss/yaml" 28 29 "k8s.io/helm/pkg/chartutil" 30 "k8s.io/helm/pkg/proto/hapi/chart" 31 "k8s.io/helm/pkg/provenance" 32 ) 33 34 const indexHTMLTemplate = ` 35 <html> 36 <head> 37 <title>Helm Repository</title> 38 </head> 39 <h1>Helm Charts Repository</h1> 40 <ul> 41 {{range $name, $ver := .Index.Entries}} 42 <li>{{$name}}<ul>{{range $ver}} 43 <li><a href="{{index .URLs 0}}">{{.Name}}-{{.Version}}</a></li> 44 {{end}}</ul> 45 </li> 46 {{end}} 47 </ul> 48 <body> 49 <p>Last Generated: {{.Index.Generated}}</p> 50 </body> 51 </html> 52 ` 53 54 // RepositoryServer is an HTTP handler for serving a chart repository. 55 type RepositoryServer struct { 56 RepoPath string 57 } 58 59 // ServeHTTP implements the http.Handler interface. 60 func (s *RepositoryServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { 61 uri := r.URL.Path 62 switch uri { 63 case "/", "/charts/", "/charts/index.html", "/charts/index": 64 w.Header().Set("Content-Type", "text/html; charset=utf-8") 65 s.htmlIndex(w, r) 66 default: 67 file := strings.TrimPrefix(uri, "/charts/") 68 http.ServeFile(w, r, filepath.Join(s.RepoPath, file)) 69 } 70 } 71 72 // StartLocalRepo starts a web server and serves files from the given path 73 func StartLocalRepo(path, address string) error { 74 if address == "" { 75 address = "127.0.0.1:8879" 76 } 77 s := &RepositoryServer{RepoPath: path} 78 return http.ListenAndServe(address, s) 79 } 80 81 func (s *RepositoryServer) htmlIndex(w http.ResponseWriter, r *http.Request) { 82 t := htemplate.Must(htemplate.New("index.html").Parse(indexHTMLTemplate)) 83 // load index 84 lrp := filepath.Join(s.RepoPath, "index.yaml") 85 i, err := LoadIndexFile(lrp) 86 if err != nil { 87 http.Error(w, err.Error(), 500) 88 return 89 } 90 data := map[string]interface{}{ 91 "Index": i, 92 } 93 if err := t.Execute(w, data); err != nil { 94 fmt.Fprintf(w, "Template error: %s", err) 95 } 96 } 97 98 // AddChartToLocalRepo saves a chart in the given path and then reindexes the index file 99 func AddChartToLocalRepo(ch *chart.Chart, path string) error { 100 _, err := chartutil.Save(ch, path) 101 if err != nil { 102 return err 103 } 104 return Reindex(ch, path+"/index.yaml") 105 } 106 107 // Reindex adds an entry to the index file at the given path 108 func Reindex(ch *chart.Chart, path string) error { 109 name := ch.Metadata.Name + "-" + ch.Metadata.Version 110 y, err := LoadIndexFile(path) 111 if err != nil { 112 return err 113 } 114 found := false 115 for k := range y.Entries { 116 if k == name { 117 found = true 118 break 119 } 120 } 121 if !found { 122 dig, err := provenance.DigestFile(path) 123 if err != nil { 124 return err 125 } 126 127 y.Add(ch.Metadata, name+".tgz", "http://127.0.0.1:8879/charts", "sha256:"+dig) 128 129 out, err := yaml.Marshal(y) 130 if err != nil { 131 return err 132 } 133 134 ioutil.WriteFile(path, out, 0644) 135 } 136 return nil 137 }