github.com/pensu/helm@v2.6.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  }