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  }