github.com/umeshredd/helm@v3.0.0-alpha.1+incompatible/pkg/repo/repotest/server.go (about)

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