mirror of
https://github.com/helm/helm.git
synced 2026-05-28 04:35:48 -04:00
fix(helm): finish repo index.html
Previous versions of Helm had placeholder text in the index.yaml file. This generates an HTML index for 'helm serve'. It also has a refactoring of the server so that the server can be tested. Closes #1397
This commit is contained in:
parent
fcdb79da16
commit
abf1ddc324
4 changed files with 163 additions and 23 deletions
|
|
@ -18,6 +18,7 @@ package repo
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
htemplate "html/template"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
|
|
@ -30,37 +31,74 @@ import (
|
|||
"k8s.io/helm/pkg/provenance"
|
||||
)
|
||||
|
||||
var localRepoPath string
|
||||
const indexHTMLTemplate = `
|
||||
<html>
|
||||
<head>
|
||||
<title>Helm Repository</title>
|
||||
</head>
|
||||
<h1>Helm Charts Repository</h1>
|
||||
<ul>
|
||||
{{range $name, $ver := .Index.Entries}}
|
||||
<li>{{$name}}<ul>{{range $ver}}
|
||||
<li><a href="{{index .URLs 0}}">{{.Name}}-{{.Version}}</a></li>
|
||||
{{end}}</ul>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
<body>
|
||||
<p>Last Generated: {{.Index.Generated}}</p>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
const indexFile = `
|
||||
Welcome to the Kubernetes Package manager!\nBrowse charts on localhost:8879/charts!
|
||||
`
|
||||
|
||||
// RepositoryServer is an HTTP handler for serving a chart repository.
|
||||
type RepositoryServer struct {
|
||||
RepoPath string
|
||||
}
|
||||
|
||||
// ServeHTTP implements the http.Handler interface.
|
||||
func (s *RepositoryServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
uri := r.URL.Path
|
||||
switch uri {
|
||||
case "/":
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
fmt.Fprintf(w, indexFile)
|
||||
case "/charts/", "/charts/index.html", "/charts/index":
|
||||
s.htmlIndex(w, r)
|
||||
default:
|
||||
file := strings.TrimPrefix(uri, "/charts/")
|
||||
http.ServeFile(w, r, filepath.Join(s.RepoPath, file))
|
||||
}
|
||||
}
|
||||
|
||||
// StartLocalRepo starts a web server and serves files from the given path
|
||||
func StartLocalRepo(path, address string) error {
|
||||
if address == "" {
|
||||
address = ":8879"
|
||||
}
|
||||
localRepoPath = path
|
||||
http.HandleFunc("/", rootHandler)
|
||||
http.HandleFunc("/charts/", indexHandler)
|
||||
return http.ListenAndServe(address, nil)
|
||||
}
|
||||
func rootHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
fmt.Fprintf(w, "Welcome to the Kubernetes Package manager!\nBrowse charts on localhost:8879/charts!")
|
||||
}
|
||||
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
file := r.URL.Path[len("/charts/"):]
|
||||
if len(strings.Split(file, ".")) > 1 {
|
||||
serveFile(w, r, file)
|
||||
} else if file == "" {
|
||||
fmt.Fprintf(w, "list of charts should be here at some point")
|
||||
} else if file == "index" {
|
||||
fmt.Fprintf(w, "index file data should be here at some point")
|
||||
} else {
|
||||
fmt.Fprintf(w, "Ummm... Nothing to see here folks")
|
||||
}
|
||||
s := &RepositoryServer{RepoPath: path}
|
||||
return http.ListenAndServe(address, s)
|
||||
}
|
||||
|
||||
func serveFile(w http.ResponseWriter, r *http.Request, file string) {
|
||||
http.ServeFile(w, r, filepath.Join(localRepoPath, file))
|
||||
func (s *RepositoryServer) htmlIndex(w http.ResponseWriter, r *http.Request) {
|
||||
t := htemplate.Must(htemplate.New("index.html").Parse(indexHTMLTemplate))
|
||||
// load index
|
||||
lrp := filepath.Join(s.RepoPath, "index.yaml")
|
||||
i, err := LoadIndexFile(lrp)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
data := map[string]interface{}{
|
||||
"Index": i,
|
||||
}
|
||||
if err := t.Execute(w, data); err != nil {
|
||||
fmt.Fprintf(w, "Template error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// AddChartToLocalRepo saves a chart in the given path and then reindexes the index file
|
||||
|
|
|
|||
61
pkg/repo/local_test.go
Normal file
61
pkg/repo/local_test.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRepositoryServer(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
path string
|
||||
expect string
|
||||
}{
|
||||
{"index YAML", "/charts/index.yaml", "apiVersion: v1"},
|
||||
{"index HTML", "/charts/index.html", "<html>"},
|
||||
{"charts root", "/charts/", "<html>"},
|
||||
{"root", "/", "Welcome"},
|
||||
{"file", "/test.txt", "Hello World"},
|
||||
}
|
||||
|
||||
s := &RepositoryServer{RepoPath: "testdata/server"}
|
||||
srv := httptest.NewServer(s)
|
||||
defer srv.Close()
|
||||
|
||||
for _, tt := range tests {
|
||||
res, err := http.Get(srv.URL + tt.path)
|
||||
if err != nil {
|
||||
t.Errorf("%s: error getting %s: %s", tt.name, tt.path, err)
|
||||
continue
|
||||
}
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
t.Errorf("%s: error reading %s: %s", tt.name, tt.path, err)
|
||||
}
|
||||
res.Body.Close()
|
||||
if !strings.Contains(string(body), tt.expect) {
|
||||
t.Errorf("%s: expected to find %q in %q", tt.name, tt.expect, string(body))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
40
pkg/repo/testdata/server/index.yaml
vendored
Normal file
40
pkg/repo/testdata/server/index.yaml
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
apiVersion: v1
|
||||
entries:
|
||||
nginx:
|
||||
- urls:
|
||||
- http://storage.googleapis.com/kubernetes-charts/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
|
||||
- urls:
|
||||
- http://storage.googleapis.com/kubernetes-charts/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
|
||||
alpine:
|
||||
- urls:
|
||||
- http://storage.googleapis.com/kubernetes-charts/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"
|
||||
|
||||
1
pkg/repo/testdata/server/test.txt
vendored
Normal file
1
pkg/repo/testdata/server/test.txt
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
Hello World
|
||||
Loading…
Reference in a new issue