Merge pull request #1204 from michelleN/repo-refactor

ref(helm): convert repo commands to new format
reviewable/pr1218/r1
Michelle Noorali 8 years ago committed by GitHub
commit dbb84a1b9e

@ -99,6 +99,7 @@ func newRootCmd(out io.Writer) *cobra.Command {
newVerifyCmd(out),
newUpdateCmd(out),
newVersionCmd(nil, out),
newRepoCmd(out),
)
return cmd
}

@ -17,183 +17,34 @@ limitations under the License.
package main
import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"io"
"github.com/gosuri/uitable"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
"k8s.io/helm/pkg/repo"
)
func init() {
repoCmd.AddCommand(repoAddCmd)
repoCmd.AddCommand(repoListCmd)
repoCmd.AddCommand(repoRemoveCmd)
repoCmd.AddCommand(repoIndexCmd)
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,
}
var repoListCmd = &cobra.Command{
Use: "list [flags]",
Short: "list chart repositories",
RunE: runRepoList,
}
var repoRemoveCmd = &cobra.Command{
Use: "remove [flags] [NAME]",
Aliases: []string{"rm"},
Short: "remove a chart repository",
RunE: runRepoRemove,
}
var repoIndexCmd = &cobra.Command{
Use: "index [flags] [DIR] [REPO_URL]",
Short: "generate an index file for a chart repository given a directory",
RunE: runRepoIndex,
}
func runRepoAdd(cmd *cobra.Command, args []string) error {
if err := checkArgsLength(len(args), "name for the chart repository", "the url of the chart repository"); err != nil {
return err
}
name, url := args[0], args[1]
if err := addRepository(name, url); err != nil {
return err
}
var repoHelm = `
This command consists of multiple subcommands to interact with chart repositories.
fmt.Println(name + " has been added to your repositories")
return nil
}
It can be used to add, remove, list, and index chart repositories.
Example usage:
$ helm repo add [NAME] [REPO_URL]
`
func runRepoList(cmd *cobra.Command, args []string) error {
f, err := repo.LoadRepositoriesFile(repositoriesFile())
if err != nil {
return err
}
if len(f.Repositories) == 0 {
return errors.New("no repositories to show")
}
table := uitable.New()
table.MaxColWidth = 50
table.AddRow("NAME", "URL")
for k, v := range f.Repositories {
table.AddRow(k, v)
}
fmt.Println(table)
return nil
type repoCmd struct {
out io.Writer
}
func runRepoRemove(cmd *cobra.Command, args []string) error {
if err := checkArgsLength(len(args), "name of chart repository"); err != nil {
return err
}
return removeRepoLine(args[0])
}
func runRepoIndex(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return fmt.Errorf("This command needs at minimum 1 argument: a path to a directory")
}
path, err := filepath.Abs(args[0])
if err != nil {
return err
}
url := ""
if len(args) == 2 {
url = args[1]
}
return index(path, url)
}
func index(dir, url string) error {
chartRepo, err := repo.LoadChartRepository(dir, url)
if err != nil {
return err
}
return chartRepo.Index()
}
func addRepository(name, url string) error {
if err := repo.DownloadIndexFile(name, url, cacheIndexFile(name)); err != nil {
return errors.New("Looks like " + url + " is not a valid chart repository or cannot be reached: " + err.Error())
}
return insertRepoLine(name, url)
}
func removeRepoLine(name string) error {
r, err := repo.LoadRepositoriesFile(repositoriesFile())
if err != nil {
return err
}
_, ok := r.Repositories[name]
if ok {
delete(r.Repositories, name)
b, err := yaml.Marshal(&r.Repositories)
if err != nil {
return err
}
if err := ioutil.WriteFile(repositoriesFile(), b, 0666); err != nil {
return err
}
if err := removeRepoCache(name); err != nil {
return err
}
} else {
return fmt.Errorf("The repository, %s, does not exist in your repositories list", name)
}
return nil
}
func removeRepoCache(name string) error {
if _, err := os.Stat(cacheIndexFile(name)); err == nil {
err = os.Remove(cacheIndexFile(name))
if err != nil {
return err
}
}
return nil
}
func insertRepoLine(name, url string) error {
f, err := repo.LoadRepositoriesFile(repositoriesFile())
if err != nil {
return err
}
_, ok := f.Repositories[name]
if ok {
return fmt.Errorf("The repository name you provided (%s) already exists. Please specify a different name.", name)
}
if f.Repositories == nil {
f.Repositories = make(map[string]string)
func newRepoCmd(out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "repo [FLAGS] add|remove|list|index [ARGS]",
Short: "add, list, remove, index chart repositories",
Long: repoHelm,
}
f.Repositories[name] = url
cmd.AddCommand(newRepoAddCmd(out))
cmd.AddCommand(newRepoListCmd(out))
cmd.AddCommand(newRepoRemoveCmd(out))
cmd.AddCommand(newRepoIndexCmd(out))
b, _ := yaml.Marshal(&f.Repositories)
return ioutil.WriteFile(repositoriesFile(), b, 0666)
return cmd
}

@ -0,0 +1,94 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"errors"
"fmt"
"io"
"io/ioutil"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
"k8s.io/helm/pkg/repo"
)
type repoAddCmd struct {
name string
url string
out io.Writer
}
func newRepoAddCmd(out io.Writer) *cobra.Command {
add := &repoAddCmd{
out: out,
}
cmd := &cobra.Command{
Use: "add [flags] [NAME] [URL]",
Short: "add a chart repository",
RunE: func(cmd *cobra.Command, args []string) error {
if err := checkArgsLength(len(args), "name for the chart repository", "the url of the chart repository"); err != nil {
return err
}
add.name = args[0]
add.url = args[1]
return add.run()
},
}
return cmd
}
func (a *repoAddCmd) run() error {
if err := addRepository(a.name, a.url); err != nil {
return err
}
fmt.Println(a.name + " has been added to your repositories")
return nil
}
func addRepository(name, url string) error {
if err := repo.DownloadIndexFile(name, url, cacheIndexFile(name)); err != nil {
return errors.New("Looks like " + url + " is not a valid chart repository or cannot be reached: " + err.Error())
}
return insertRepoLine(name, url)
}
func insertRepoLine(name, url string) error {
f, err := repo.LoadRepositoriesFile(repositoriesFile())
if err != nil {
return err
}
_, ok := f.Repositories[name]
if ok {
return fmt.Errorf("The repository name you provided (%s) already exists. Please specify a different name.", name)
}
if f.Repositories == nil {
f.Repositories = make(map[string]string)
}
f.Repositories[name] = url
b, _ := yaml.Marshal(&f.Repositories)
return ioutil.WriteFile(repositoriesFile(), b, 0666)
}

@ -17,6 +17,7 @@ limitations under the License.
package main
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
@ -28,10 +29,30 @@ import (
"k8s.io/helm/pkg/repo"
)
var (
testName = "test-name"
testURL = "test-url"
)
var testName = "test-name"
func TestRepoAddCmd(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprintln(w, "OK")
}))
tests := []releaseCase{
{
name: "add a repository",
args: []string{testName, ts.URL},
expected: testName + " has been added to your repositories",
},
}
for _, tt := range tests {
buf := bytes.NewBuffer(nil)
c := newRepoAddCmd(buf)
if err := c.RunE(c, tt.args); err != nil {
t.Errorf("%q: expected '%q', got '%q'", tt.name, tt.expected, err)
}
}
}
func TestRepoAdd(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@ -66,39 +87,3 @@ func TestRepoAdd(t *testing.T) {
}
}
func TestRepoRemove(t *testing.T) {
home := createTmpHome()
helmHome = home
if err := ensureHome(); err != nil {
t.Errorf("%s", err)
}
if err := removeRepoLine(testName); err == nil {
t.Errorf("Expected error removing %s, but did not get one.", testName)
}
if err := insertRepoLine(testName, testURL); err != nil {
t.Errorf("%s", err)
}
mf, _ := os.Create(cacheIndexFile(testName))
mf.Close()
if err := removeRepoLine(testName); err != nil {
t.Errorf("Error removing %s from repositories", testName)
}
if _, err := os.Stat(cacheIndexFile(testName)); err == nil {
t.Errorf("Error cache file was not removed for repository %s", testName)
}
f, err := repo.LoadRepositoriesFile(repositoriesFile())
if err != nil {
t.Errorf("%s", err)
}
if _, ok := f.Repositories[testName]; ok {
t.Errorf("%s was not successfully removed from repositories list", testName)
}
}

@ -0,0 +1,75 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"io"
"path/filepath"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/repo"
)
type repoIndexCmd struct {
dir string
url string
out io.Writer
}
func newRepoIndexCmd(out io.Writer) *cobra.Command {
index := &repoIndexCmd{
out: out,
}
cmd := &cobra.Command{
Use: "index [flags] [DIR]",
Short: "generate an index file given a directory containing packaged charts",
RunE: func(cmd *cobra.Command, args []string) error {
if err := checkArgsLength(len(args), "path to a directory"); err != nil {
return err
}
index.dir = args[0]
return index.run()
},
}
f := cmd.Flags()
f.StringVar(&index.url, "url", "", "url of chart repository")
return cmd
}
func (i *repoIndexCmd) run() error {
path, err := filepath.Abs(i.dir)
if err != nil {
return err
}
return index(path, i.url)
}
func index(dir, url string) error {
chartRepo, err := repo.LoadChartRepository(dir, url)
if err != nil {
return err
}
return chartRepo.Index()
}

@ -0,0 +1,56 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"bytes"
"io/ioutil"
"os"
"path/filepath"
"testing"
"k8s.io/helm/pkg/repo"
)
func TestRepoIndexCmd(t *testing.T) {
dir, err := ioutil.TempDir("", "helm-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
if err := os.Link("testdata/testcharts/compressedchart-0.1.0.tgz", filepath.Join(dir, "compressedchart-0.1.0.tgz")); err != nil {
t.Fatal(err)
}
buf := bytes.NewBuffer(nil)
c := newRepoIndexCmd(buf)
if err := c.RunE(c, []string{dir}); err != nil {
t.Errorf("%q", err)
}
index, err := repo.LoadIndexFile(filepath.Join(dir, "index.yaml"))
if err != nil {
t.Fatal(err)
}
if len(index.Entries) != 1 {
t.Errorf("expected 1 entry, got %v: %#v", len(index.Entries), index.Entries)
}
}

@ -0,0 +1,66 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"errors"
"fmt"
"io"
"github.com/gosuri/uitable"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/repo"
)
type repoListCmd struct {
out io.Writer
}
func newRepoListCmd(out io.Writer) *cobra.Command {
list := &repoListCmd{
out: out,
}
cmd := &cobra.Command{
Use: "list [flags]",
Short: "list chart repositories",
RunE: func(cmd *cobra.Command, args []string) error {
return list.run()
},
}
return cmd
}
func (a *repoListCmd) run() error {
f, err := repo.LoadRepositoriesFile(repositoriesFile())
if err != nil {
return err
}
if len(f.Repositories) == 0 {
return errors.New("no repositories to show")
}
table := uitable.New()
table.MaxColWidth = 50
table.AddRow("NAME", "URL")
for k, v := range f.Repositories {
table.AddRow(k, v)
}
fmt.Println(table)
return nil
}

@ -0,0 +1,99 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"io"
"io/ioutil"
"os"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
"k8s.io/helm/pkg/repo"
)
type repoRemoveCmd struct {
out io.Writer
name string
}
func newRepoRemoveCmd(out io.Writer) *cobra.Command {
remove := &repoRemoveCmd{
out: out,
}
cmd := &cobra.Command{
Use: "remove [flags] [NAME]",
Aliases: []string{"rm"},
Short: "remove a chart repository",
RunE: func(cmd *cobra.Command, args []string) error {
if err := checkArgsLength(len(args), "name of chart repository"); err != nil {
return err
}
remove.name = args[0]
return remove.run()
},
}
return cmd
}
func (r *repoRemoveCmd) run() error {
return removeRepoLine(r.name)
}
func removeRepoLine(name string) error {
r, err := repo.LoadRepositoriesFile(repositoriesFile())
if err != nil {
return err
}
_, ok := r.Repositories[name]
if ok {
delete(r.Repositories, name)
b, err := yaml.Marshal(&r.Repositories)
if err != nil {
return err
}
if err := ioutil.WriteFile(repositoriesFile(), b, 0666); err != nil {
return err
}
if err := removeRepoCache(name); err != nil {
return err
}
} else {
return fmt.Errorf("The repository, %s, does not exist in your repositories list", name)
}
fmt.Println(name + " has been removed from your repositories")
return nil
}
func removeRepoCache(name string) error {
if _, err := os.Stat(cacheIndexFile(name)); err == nil {
err = os.Remove(cacheIndexFile(name))
if err != nil {
return err
}
}
return nil
}

@ -0,0 +1,61 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"os"
"testing"
"k8s.io/helm/pkg/repo"
)
func TestRepoRemove(t *testing.T) {
testURL := "https://test-url.com"
home := createTmpHome()
helmHome = home
if err := ensureHome(); err != nil {
t.Errorf("%s", err)
}
if err := removeRepoLine(testName); err == nil {
t.Errorf("Expected error removing %s, but did not get one.", testName)
}
if err := insertRepoLine(testName, testURL); err != nil {
t.Errorf("%s", err)
}
mf, _ := os.Create(cacheIndexFile(testName))
mf.Close()
if err := removeRepoLine(testName); err != nil {
t.Errorf("Error removing %s from repositories", testName)
}
if _, err := os.Stat(cacheIndexFile(testName)); err == nil {
t.Errorf("Error cache file was not removed for repository %s", testName)
}
f, err := repo.LoadRepositoriesFile(repositoriesFile())
if err != nil {
t.Errorf("%s", err)
}
if _, ok := f.Repositories[testName]; ok {
t.Errorf("%s was not successfully removed from repositories list", testName)
}
}
Loading…
Cancel
Save