github.com/cloudposse/helm@v2.2.3+incompatible/pkg/repo/repotest/server.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors All rights reserved. 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 16 package repotest 17 18 import ( 19 "io/ioutil" 20 "net/http" 21 "net/http/httptest" 22 "os" 23 "path/filepath" 24 25 "github.com/ghodss/yaml" 26 27 "k8s.io/helm/cmd/helm/helmpath" 28 "k8s.io/helm/pkg/repo" 29 ) 30 31 // NewTempServer creates a server inside of a temp dir. 32 // 33 // If the passed in string is not "", it will be treated as a shell glob, and files 34 // will be copied from that path to the server's docroot. 35 // 36 // The caller is responsible for destroying the temp directory as well as stopping 37 // the server. 38 func NewTempServer(glob string) (*Server, string, error) { 39 tdir, err := ioutil.TempDir("", "helm-repotest-") 40 if err != nil { 41 return nil, tdir, err 42 } 43 srv := NewServer(tdir) 44 45 if glob != "" { 46 if _, err := srv.CopyCharts(glob); err != nil { 47 srv.Stop() 48 return srv, tdir, err 49 } 50 } 51 52 return srv, tdir, nil 53 } 54 55 // NewServer creates a repository server for testing. 56 // 57 // docroot should be a temp dir managed by the caller. 58 // 59 // This will start the server, serving files off of the docroot. 60 // 61 // Use CopyCharts to move charts into the repository and then index them 62 // for service. 63 func NewServer(docroot string) *Server { 64 root, err := filepath.Abs(docroot) 65 if err != nil { 66 panic(err) 67 } 68 srv := &Server{ 69 docroot: root, 70 } 71 srv.start() 72 // Add the testing repository as the only repo. 73 if err := setTestingRepository(helmpath.Home(docroot), "test", srv.URL()); err != nil { 74 panic(err) 75 } 76 return srv 77 } 78 79 // Server is an implementation of a repository server for testing. 80 type Server struct { 81 docroot string 82 srv *httptest.Server 83 } 84 85 // Root gets the docroot for the server. 86 func (s *Server) Root() string { 87 return s.docroot 88 } 89 90 // CopyCharts takes a glob expression and copies those charts to the server root. 91 func (s *Server) CopyCharts(origin string) ([]string, error) { 92 files, err := filepath.Glob(origin) 93 if err != nil { 94 return []string{}, err 95 } 96 copied := make([]string, len(files)) 97 for i, f := range files { 98 base := filepath.Base(f) 99 newname := filepath.Join(s.docroot, base) 100 data, err := ioutil.ReadFile(f) 101 if err != nil { 102 return []string{}, err 103 } 104 if err := ioutil.WriteFile(newname, data, 0755); err != nil { 105 return []string{}, err 106 } 107 copied[i] = newname 108 } 109 110 err = s.CreateIndex() 111 return copied, err 112 } 113 114 // CreateIndex will read docroot and generate an index.yaml file. 115 func (s *Server) CreateIndex() error { 116 // generate the index 117 index, err := repo.IndexDirectory(s.docroot, s.URL()) 118 if err != nil { 119 return err 120 } 121 122 d, err := yaml.Marshal(index) 123 if err != nil { 124 return err 125 } 126 127 ifile := filepath.Join(s.docroot, "index.yaml") 128 return ioutil.WriteFile(ifile, d, 0755) 129 } 130 131 func (s *Server) start() { 132 s.srv = httptest.NewServer(http.FileServer(http.Dir(s.docroot))) 133 } 134 135 // Stop stops the server and closes all connections. 136 // 137 // It should be called explicitly. 138 func (s *Server) Stop() { 139 s.srv.Close() 140 } 141 142 // URL returns the URL of the server. 143 // 144 // Example: 145 // http://localhost:1776 146 func (s *Server) URL() string { 147 return s.srv.URL 148 } 149 150 // LinkIndices links the index created with CreateIndex and makes a symboic link to the repositories/cache directory. 151 // 152 // This makes it possible to simulate a local cache of a repository. 153 func (s *Server) LinkIndices() error { 154 destfile := "test-index.yaml" 155 // Link the index.yaml file to the 156 lstart := filepath.Join(s.docroot, "index.yaml") 157 ldest := filepath.Join(s.docroot, "repository/cache", destfile) 158 return os.Symlink(lstart, ldest) 159 } 160 161 // setTestingRepository sets up a testing repository.yaml with only the given name/URL. 162 func setTestingRepository(home helmpath.Home, name, url string) error { 163 r := repo.NewRepoFile() 164 r.Add(&repo.Entry{ 165 Name: name, 166 URL: url, 167 Cache: home.CacheIndex(name), 168 }) 169 os.MkdirAll(filepath.Join(home.Repository(), name), 0755) 170 return r.WriteFile(home.RepositoryFile(), 0644) 171 }