github.com/koderover/helm@v2.17.0+incompatible/pkg/repo/repo.go (about)

     1  /*
     2  Copyright The Helm Authors.
     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 // import "k8s.io/helm/pkg/repo"
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"io/ioutil"
    23  	"os"
    24  	"time"
    25  
    26  	"github.com/ghodss/yaml"
    27  )
    28  
    29  // ErrRepoOutOfDate indicates that the repository file is out of date, but
    30  // is fixable.
    31  var ErrRepoOutOfDate = errors.New("repository file is out of date")
    32  
    33  // RepoFile represents the repositories.yaml file in $HELM_HOME
    34  // TODO: change type name to File in Helm 3 to resolve linter warning
    35  type RepoFile struct { // nolint
    36  	APIVersion   string    `json:"apiVersion"`
    37  	Generated    time.Time `json:"generated"`
    38  	Repositories []*Entry  `json:"repositories"`
    39  }
    40  
    41  // NewRepoFile generates an empty repositories file.
    42  //
    43  // Generated and APIVersion are automatically set.
    44  func NewRepoFile() *RepoFile {
    45  	return &RepoFile{
    46  		APIVersion:   APIVersionV1,
    47  		Generated:    time.Now(),
    48  		Repositories: []*Entry{},
    49  	}
    50  }
    51  
    52  // LoadRepositoriesFile takes a file at the given path and returns a RepoFile object
    53  //
    54  // If this returns ErrRepoOutOfDate, it also returns a recovered RepoFile that
    55  // can be saved as a replacement to the out of date file.
    56  func LoadRepositoriesFile(path string) (*RepoFile, error) {
    57  	b, err := ioutil.ReadFile(path)
    58  	if err != nil {
    59  		if os.IsNotExist(err) {
    60  			return nil, fmt.Errorf(
    61  				"Couldn't load repositories file (%s).\n"+
    62  					"You might need to run `helm init` (or "+
    63  					"`helm init --client-only` if tiller is "+
    64  					"already installed)", path)
    65  		}
    66  		return nil, err
    67  	}
    68  
    69  	r := &RepoFile{}
    70  	err = yaml.Unmarshal(b, r)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	// File is either corrupt, or is from before v2.0.0-Alpha.5
    76  	if r.APIVersion == "" {
    77  		m := map[string]string{}
    78  		if err = yaml.Unmarshal(b, &m); err != nil {
    79  			return nil, err
    80  		}
    81  		r := NewRepoFile()
    82  		for k, v := range m {
    83  			r.Add(&Entry{
    84  				Name:  k,
    85  				URL:   v,
    86  				Cache: fmt.Sprintf("%s-index.yaml", k),
    87  			})
    88  		}
    89  		return r, ErrRepoOutOfDate
    90  	}
    91  
    92  	return r, nil
    93  }
    94  
    95  // Add adds one or more repo entries to a repo file.
    96  func (r *RepoFile) Add(re ...*Entry) {
    97  	r.Repositories = append(r.Repositories, re...)
    98  }
    99  
   100  // Update attempts to replace one or more repo entries in a repo file. If an
   101  // entry with the same name doesn't exist in the repo file it will add it.
   102  func (r *RepoFile) Update(re ...*Entry) {
   103  	for _, target := range re {
   104  		found := false
   105  		for j, repo := range r.Repositories {
   106  			if repo.Name == target.Name {
   107  				r.Repositories[j] = target
   108  				found = true
   109  				break
   110  			}
   111  		}
   112  		if !found {
   113  			r.Add(target)
   114  		}
   115  	}
   116  }
   117  
   118  // Has returns true if the given name is already a repository name.
   119  func (r *RepoFile) Has(name string) bool {
   120  	_, ok := r.Get(name)
   121  	return ok
   122  }
   123  
   124  // Get returns entry by the given name if it exists.
   125  func (r *RepoFile) Get(name string) (*Entry, bool) {
   126  	for _, entry := range r.Repositories {
   127  		if entry.Name == name {
   128  			return entry, true
   129  		}
   130  	}
   131  	return nil, false
   132  }
   133  
   134  // Remove removes the entry from the list of repositories.
   135  func (r *RepoFile) Remove(name string) bool {
   136  	cp := []*Entry{}
   137  	found := false
   138  	for _, rf := range r.Repositories {
   139  		if rf.Name == name {
   140  			found = true
   141  			continue
   142  		}
   143  		cp = append(cp, rf)
   144  	}
   145  	r.Repositories = cp
   146  	return found
   147  }
   148  
   149  // WriteFile writes a repositories file to the given path.
   150  func (r *RepoFile) WriteFile(path string, perm os.FileMode) error {
   151  	data, err := yaml.Marshal(r)
   152  	if err != nil {
   153  		return err
   154  	}
   155  	return ioutil.WriteFile(path, data, perm)
   156  }