diff --git a/cmd/helm/repo.go b/cmd/helm/repo.go new file mode 100644 index 000000000..e60bd5f41 --- /dev/null +++ b/cmd/helm/repo.go @@ -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 +} diff --git a/cmd/helm/repo_test.go b/cmd/helm/repo_test.go new file mode 100644 index 000000000..f4c234ebf --- /dev/null +++ b/cmd/helm/repo_test.go @@ -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") + } + +} diff --git a/pkg/repo/repo.go b/pkg/repo/repo.go new file mode 100644 index 000000000..13138c10d --- /dev/null +++ b/pkg/repo/repo.go @@ -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 +}