Merge pull request #68 from michelleN/helm-repo

feat(helm): add helm repo add command
pull/613/head
Michelle Noorali 9 years ago
commit 0ebeecbdd8

@ -1,8 +1,6 @@
package main
import (
"os"
"github.com/spf13/cobra"
)
@ -25,7 +23,3 @@ func init() {
func home(cmd *cobra.Command, args []string) {
cmd.Printf(homePath() + "\n")
}
func homePath() string {
return os.ExpandEnv(helmHome)
}

@ -5,7 +5,6 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/deis/tiller/pkg/client"
"github.com/deis/tiller/pkg/kubectl"
@ -17,13 +16,10 @@ This command installs Tiller (the helm server side component) onto your
Kubernetes Cluster and sets up local configuration in $HELM_HOME (default: ~/.helm/)
`
var repositoriesFilePath string
var cachePath string
var localRepoPath string
var localCacheFilePath string
var tillerImg string
var defaultRepo = map[string]string{"default-name": "default-url"}
var (
tillerImg string
defaultRepo = map[string]string{"default-name": "default-url"}
)
func init() {
initCmd.Flags().StringVarP(&tillerImg, "tiller-image", "i", "", "override tiller image")
@ -43,7 +39,7 @@ func runInit(cmd *cobra.Command, args []string) error {
return errors.New("This command does not accept arguments. \n")
}
if err := ensureHome(homePath()); err != nil {
if err := ensureHome(); err != nil {
return err
}
@ -81,14 +77,8 @@ func buildKubectlRunner(kubectlPath string) kubectl.Runner {
// ensureHome checks to see if $HELM_HOME exists
//
// If $HELM_HOME does not exist, this function will create it.
func ensureHome(home string) error {
repositoriesFilePath = filepath.Join(home, "repositories.yaml")
cachePath = filepath.Join(home, "cache")
localRepoPath = filepath.Join(home, "local")
localCacheFilePath = filepath.Join(home, "cache.yaml")
fmt.Println("home path: " + home)
configDirectories := []string{home, cachePath, localRepoPath}
func ensureHome() error {
configDirectories := []string{homePath(), cacheDirectory(), localRepoDirectory()}
for _, p := range configDirectories {
if fi, err := os.Stat(p); err != nil {
@ -101,28 +91,30 @@ func ensureHome(home string) error {
}
}
if fi, err := os.Stat(repositoriesFilePath); err != nil {
fmt.Printf("Creating %s \n", repositoriesFilePath)
if err := ioutil.WriteFile(repositoriesFilePath, []byte("local: localhost:8879/charts\n"), 0644); err != nil {
repoFile := repositoriesFile()
if fi, err := os.Stat(repoFile); err != nil {
fmt.Printf("Creating %s \n", repoFile)
if err := ioutil.WriteFile(repoFile, []byte("local: localhost:8879/charts\n"), 0644); err != nil {
return err
}
} else if fi.IsDir() {
return fmt.Errorf("%s must be a file, not a directory", repositoriesFilePath)
return fmt.Errorf("%s must be a file, not a directory", repoFile)
}
if fi, err := os.Stat(localCacheFilePath); err != nil {
fmt.Printf("Creating %s \n", localCacheFilePath)
_, err := os.Create(localCacheFilePath)
localRepoCacheFile := localRepoDirectory(localRepoCacheFilePath)
if fi, err := os.Stat(localRepoCacheFile); err != nil {
fmt.Printf("Creating %s \n", localRepoCacheFile)
_, err := os.Create(localRepoCacheFile)
if err != nil {
return err
}
//TODO: take this out and replace with helm update functionality
os.Symlink(localCacheFilePath, filepath.Join(cachePath, "local-cache.yaml"))
os.Symlink(localRepoCacheFile, cacheDirectory("local-cache.yaml"))
} else if fi.IsDir() {
return fmt.Errorf("%s must be a file, not a directory", localCacheFilePath)
return fmt.Errorf("%s must be a file, not a directory", localRepoCacheFile)
}
fmt.Printf("$HELM_HOME has also been configured at %s.\n", helmHome)
fmt.Printf("$HELM_HOME has been configured at %s.\n", helmHome)
return nil
}

@ -8,11 +8,12 @@ import (
func TestEnsureHome(t *testing.T) {
home := createTmpHome()
if err := ensureHome(home); err != nil {
helmHome = home
if err := ensureHome(); err != nil {
t.Errorf("%s", err)
}
expectedDirs := []string{home, cachePath, localRepoPath}
expectedDirs := []string{homePath(), cacheDirectory(), localRepoDirectory()}
for _, dir := range expectedDirs {
if fi, err := os.Stat(dir); err != nil {
t.Errorf("%s", err)
@ -21,13 +22,13 @@ func TestEnsureHome(t *testing.T) {
}
}
if fi, err := os.Stat(repositoriesFilePath); err != nil {
if fi, err := os.Stat(repositoriesFile()); err != nil {
t.Errorf("%s", err)
} else if fi.IsDir() {
t.Errorf("%s should not be a directory", fi)
}
if fi, err := os.Stat(localCacheFilePath); err != nil {
if fi, err := os.Stat(localRepoDirectory(localRepoCacheFilePath)); err != nil {
t.Errorf("%s", err)
} else if fi.IsDir() {
t.Errorf("%s should not be a directory", fi)

@ -56,7 +56,7 @@ func runPackage(cmd *cobra.Command, args []string) error {
// Save to $HELM_HOME/local directory.
if save {
if err := repo.AddChartToLocalRepo(ch, localRepoPath); err != nil {
if err := repo.AddChartToLocalRepo(ch, localRepoDirectory()); err != nil {
return err
}
}

@ -0,0 +1,72 @@
package main
import (
"fmt"
"os"
"github.com/deis/tiller/pkg/repo"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
)
func init() {
repoCmd.AddCommand(repoAddCmd)
RootCommand.AddCommand(repoCmd)
}
var repoCmd = &cobra.Command{
Use: "repo add|remove|list [ARG]",
Short: "add, list, or remove chart repositories",
}
var repoAddCmd = &cobra.Command{
Use: "add [flags] [NAME] [URL]",
Short: "add a chart repository",
RunE: runRepoAdd,
}
func runRepoAdd(cmd *cobra.Command, args []string) error {
if len(args) != 2 {
return fmt.Errorf("This command needs two argument, a name for the chart repository and the url of the chart repository")
}
err := insertRepoLine(args[0], args[1])
if err != nil {
return err
}
fmt.Println(args[0] + " has been added to your repositories")
return nil
}
func insertRepoLine(name, url string) error {
err := checkUniqueName(name)
if err != nil {
return err
}
b, _ := yaml.Marshal(map[string]string{name: url})
f, err := os.OpenFile(repositoriesFile(), os.O_APPEND|os.O_WRONLY, 0666)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write(b)
if err != nil {
return err
}
return nil
}
func checkUniqueName(name string) error {
file, err := repo.LoadRepositoriesFile(repositoriesFile())
if err != nil {
return err
}
_, ok := file.Repositories[name]
if ok {
return fmt.Errorf("The repository name you provided (%s) already exists. Please specifiy a different name.", name)
}
return nil
}

@ -0,0 +1,35 @@
package main
import (
"testing"
"github.com/deis/tiller/pkg/repo"
)
func TestRepoAdd(t *testing.T) {
home := createTmpHome()
helmHome = home
if err := ensureHome(); err != nil {
t.Errorf("%s", err)
}
testName := "test-name"
testURL := "test-url"
if err := insertRepoLine(testName, testURL); err != nil {
t.Errorf("%s", err)
}
f, err := repo.LoadRepositoriesFile(repositoriesFile())
if err != nil {
t.Errorf("%s", err)
}
_, ok := f.Repositories[testName]
if !ok {
t.Errorf("%s was not successfully inserted into %s", testName, repositoriesFile())
}
if err := insertRepoLine(testName, testURL); err == nil {
t.Errorf("Duplicate repository name was added")
}
}

@ -40,7 +40,7 @@ func search(cmd *cobra.Command, args []string) error {
func searchCacheForPattern(name string) ([]string, error) {
fileList := []string{}
filepath.Walk(cachePath, func(path string, f os.FileInfo, err error) error {
filepath.Walk(cacheDirectory(), func(path string, f os.FileInfo, err error) error {
if !f.IsDir() {
fileList = append(fileList, path)
}

@ -22,5 +22,5 @@ var serveCmd = &cobra.Command{
}
func serve(cmd *cobra.Command, args []string) {
repo.StartLocalRepo(localRepoPath)
repo.StartLocalRepo(localRepoDirectory())
}

@ -0,0 +1,31 @@
package main
import (
"os"
"path/filepath"
)
const (
repositoriesFilePath string = "repositories.yaml"
cachePath string = "cache"
localRepoPath string = "local"
localRepoCacheFilePath string = "cache.yaml"
)
func homePath() string {
return os.ExpandEnv(helmHome)
}
func cacheDirectory(paths ...string) string {
fragments := append([]string{homePath(), cachePath}, paths...)
return filepath.Join(fragments...)
}
func localRepoDirectory(paths ...string) string {
fragments := append([]string{homePath(), localRepoPath}, paths...)
return filepath.Join(fragments...)
}
func repositoriesFile() string {
return filepath.Join(homePath(), repositoriesFilePath)
}

@ -0,0 +1,40 @@
package repo
import (
"io/ioutil"
"gopkg.in/yaml.v2"
)
// RepoFile represents the .repositories file in $HELM_HOME
type RepoFile struct {
Repositories map[string]string
}
// LoadRepositoriesFile takes a file at the given path and returns a RepoFile object
func LoadRepositoriesFile(path string) (*RepoFile, error) {
b, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
var r RepoFile
err = yaml.Unmarshal(b, &r)
if err != nil {
return nil, err
}
return &r, nil
}
// UnmarshalYAML unmarshals the repo file
func (rf *RepoFile) UnmarshalYAML(unmarshal func(interface{}) error) error {
var repos map[string]string
if err := unmarshal(&repos); err != nil {
if _, ok := err.(*yaml.TypeError); !ok {
return err
}
}
rf.Repositories = repos
return nil
}
Loading…
Cancel
Save