Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
H
helm3
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
helm3
Commits
4bb36c89
Commit
4bb36c89
authored
May 10, 2016
by
Michelle Noorali
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(helm): generate index file for repository
parent
d36615e3
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
329 additions
and
102 deletions
+329
-102
repo.go
cmd/helm/repo.go
+37
-0
search.go
cmd/helm/search.go
+1
-1
local.go
pkg/repo/local.go
+1
-44
local_test.go
pkg/repo/local_test.go
+0
-41
repo.go
pkg/repo/repo.go
+154
-1
repo_test.go
pkg/repo/repo_test.go
+114
-0
local-index.yaml
pkg/repo/testdata/local-index.yaml
+19
-15
repositories.yaml
pkg/repo/testdata/repositories.yaml
+3
-0
frobnitz-1.2.3.tgz
pkg/repo/testdata/repository/frobnitz-1.2.3.tgz
+0
-0
sprocket-1.2.0.tgz
pkg/repo/testdata/repository/sprocket-1.2.0.tgz
+0
-0
No files found.
cmd/helm/repo.go
View file @
4bb36c89
...
@@ -4,6 +4,7 @@ import (
...
@@ -4,6 +4,7 @@ import (
"errors"
"errors"
"fmt"
"fmt"
"io/ioutil"
"io/ioutil"
"path/filepath"
"github.com/gosuri/uitable"
"github.com/gosuri/uitable"
"github.com/kubernetes/helm/pkg/repo"
"github.com/kubernetes/helm/pkg/repo"
...
@@ -15,6 +16,7 @@ func init() {
...
@@ -15,6 +16,7 @@ func init() {
repoCmd
.
AddCommand
(
repoAddCmd
)
repoCmd
.
AddCommand
(
repoAddCmd
)
repoCmd
.
AddCommand
(
repoListCmd
)
repoCmd
.
AddCommand
(
repoListCmd
)
repoCmd
.
AddCommand
(
repoRemoveCmd
)
repoCmd
.
AddCommand
(
repoRemoveCmd
)
repoCmd
.
AddCommand
(
repoIndexCmd
)
RootCommand
.
AddCommand
(
repoCmd
)
RootCommand
.
AddCommand
(
repoCmd
)
}
}
...
@@ -41,6 +43,12 @@ var repoRemoveCmd = &cobra.Command{
...
@@ -41,6 +43,12 @@ var repoRemoveCmd = &cobra.Command{
RunE
:
runRepoRemove
,
RunE
:
runRepoRemove
,
}
}
var
repoIndexCmd
=
&
cobra
.
Command
{
Use
:
"index [flags] [DIR]"
,
Short
:
"generate an index file for a chart repository given a directory"
,
RunE
:
runRepoIndex
,
}
func
runRepoAdd
(
cmd
*
cobra
.
Command
,
args
[]
string
)
error
{
func
runRepoAdd
(
cmd
*
cobra
.
Command
,
args
[]
string
)
error
{
if
err
:=
checkArgsLength
(
2
,
len
(
args
),
"name for the chart repository"
,
"the url of the chart repository"
);
err
!=
nil
{
if
err
:=
checkArgsLength
(
2
,
len
(
args
),
"name for the chart repository"
,
"the url of the chart repository"
);
err
!=
nil
{
return
err
return
err
...
@@ -87,6 +95,35 @@ func runRepoRemove(cmd *cobra.Command, args []string) error {
...
@@ -87,6 +95,35 @@ func runRepoRemove(cmd *cobra.Command, args []string) error {
return
nil
return
nil
}
}
func
runRepoIndex
(
cmd
*
cobra
.
Command
,
args
[]
string
)
error
{
if
err
:=
checkArgsLength
(
1
,
len
(
args
),
"path to a directory"
);
err
!=
nil
{
return
err
}
path
,
err
:=
filepath
.
Abs
(
args
[
0
])
if
err
!=
nil
{
return
err
}
if
err
:=
index
(
path
);
err
!=
nil
{
return
err
}
return
nil
}
func
index
(
dir
string
)
error
{
chartRepo
,
err
:=
repo
.
LoadChartRepository
(
dir
)
if
err
!=
nil
{
return
err
}
if
err
:=
chartRepo
.
Index
();
err
!=
nil
{
return
err
}
return
nil
}
func
removeRepoLine
(
name
string
)
error
{
func
removeRepoLine
(
name
string
)
error
{
r
,
err
:=
repo
.
LoadRepositoriesFile
(
repositoriesFile
())
r
,
err
:=
repo
.
LoadRepositoriesFile
(
repositoriesFile
())
if
err
!=
nil
{
if
err
!=
nil
{
...
...
cmd/helm/search.go
View file @
4bb36c89
...
@@ -49,7 +49,7 @@ func searchChartRefsForPattern(search string, chartRefs map[string]*repo.ChartRe
...
@@ -49,7 +49,7 @@ func searchChartRefsForPattern(search string, chartRefs map[string]*repo.ChartRe
matches
=
append
(
matches
,
k
)
matches
=
append
(
matches
,
k
)
continue
continue
}
}
for
_
,
keyword
:=
range
c
.
Keywords
{
for
_
,
keyword
:=
range
c
.
Chartfile
.
Keywords
{
if
strings
.
Contains
(
keyword
,
search
)
{
if
strings
.
Contains
(
keyword
,
search
)
{
matches
=
append
(
matches
,
k
)
matches
=
append
(
matches
,
k
)
}
}
...
...
pkg/repo/local.go
View file @
4bb36c89
...
@@ -8,7 +8,6 @@ import (
...
@@ -8,7 +8,6 @@ import (
"strings"
"strings"
"github.com/kubernetes/helm/pkg/chart"
"github.com/kubernetes/helm/pkg/chart"
"gopkg.in/yaml.v2"
)
)
var
localRepoPath
string
var
localRepoPath
string
...
@@ -55,22 +54,6 @@ func AddChartToLocalRepo(ch *chart.Chart, path string) error {
...
@@ -55,22 +54,6 @@ func AddChartToLocalRepo(ch *chart.Chart, path string) error {
return
nil
return
nil
}
}
// LoadIndexFile takes a file at the given path and returns an IndexFile object
func
LoadIndexFile
(
path
string
)
(
*
IndexFile
,
error
)
{
b
,
err
:=
ioutil
.
ReadFile
(
path
)
if
err
!=
nil
{
return
nil
,
err
}
//TODO: change variable name - y is not helpful :P
var
y
IndexFile
err
=
yaml
.
Unmarshal
(
b
,
&
y
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
y
,
nil
}
// Reindex adds an entry to the index file at the given path
// Reindex adds an entry to the index file at the given path
func
Reindex
(
ch
*
chart
.
Chart
,
path
string
)
error
{
func
Reindex
(
ch
*
chart
.
Chart
,
path
string
)
error
{
name
:=
ch
.
Chartfile
()
.
Name
+
"-"
+
ch
.
Chartfile
()
.
Version
name
:=
ch
.
Chartfile
()
.
Name
+
"-"
+
ch
.
Chartfile
()
.
Version
...
@@ -88,7 +71,7 @@ func Reindex(ch *chart.Chart, path string) error {
...
@@ -88,7 +71,7 @@ func Reindex(ch *chart.Chart, path string) error {
if
!
found
{
if
!
found
{
url
:=
"localhost:8879/charts/"
+
name
+
".tgz"
url
:=
"localhost:8879/charts/"
+
name
+
".tgz"
out
,
err
:=
y
.
insertChart
Entry
(
name
,
url
)
out
,
err
:=
y
.
add
Entry
(
name
,
url
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -97,29 +80,3 @@ func Reindex(ch *chart.Chart, path string) error {
...
@@ -97,29 +80,3 @@ func Reindex(ch *chart.Chart, path string) error {
}
}
return
nil
return
nil
}
}
// UnmarshalYAML unmarshals the index file
func
(
i
*
IndexFile
)
UnmarshalYAML
(
unmarshal
func
(
interface
{})
error
)
error
{
var
refs
map
[
string
]
*
ChartRef
if
err
:=
unmarshal
(
&
refs
);
err
!=
nil
{
if
_
,
ok
:=
err
.
(
*
yaml
.
TypeError
);
!
ok
{
return
err
}
}
i
.
Entries
=
refs
return
nil
}
func
(
i
*
IndexFile
)
insertChartEntry
(
name
string
,
url
string
)
([]
byte
,
error
)
{
if
i
.
Entries
==
nil
{
i
.
Entries
=
make
(
map
[
string
]
*
ChartRef
)
}
entry
:=
ChartRef
{
Name
:
name
,
URL
:
url
}
i
.
Entries
[
name
]
=
&
entry
out
,
err
:=
yaml
.
Marshal
(
&
i
.
Entries
)
if
err
!=
nil
{
return
nil
,
err
}
return
out
,
nil
}
pkg/repo/local_test.go
deleted
100644 → 0
View file @
d36615e3
package
repo
import
(
"testing"
)
const
testfile
=
"testdata/local-index.yaml"
func
TestLoadIndexFile
(
t
*
testing
.
T
)
{
cf
,
err
:=
LoadIndexFile
(
testfile
)
if
err
!=
nil
{
t
.
Errorf
(
"Failed to load index file: %s"
,
err
)
}
if
len
(
cf
.
Entries
)
!=
2
{
t
.
Errorf
(
"Expected 2 entries in the index file, but got %d"
,
len
(
cf
.
Entries
))
}
nginx
:=
false
alpine
:=
false
for
k
,
e
:=
range
cf
.
Entries
{
if
k
==
"nginx-0.1.0"
{
if
e
.
Name
==
"nginx"
{
if
len
(
e
.
Keywords
)
==
3
{
nginx
=
true
}
}
}
if
k
==
"alpine-1.0.0"
{
if
e
.
Name
==
"alpine"
{
if
len
(
e
.
Keywords
)
==
4
{
alpine
=
true
}
}
}
}
if
!
nginx
{
t
.
Errorf
(
"nginx entry was not decoded properly"
)
}
if
!
alpine
{
t
.
Errorf
(
"alpine entry was not decoded properly"
)
}
}
pkg/repo/repo.go
View file @
4bb36c89
package
repo
package
repo
import
(
import
(
"errors"
"io/ioutil"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/kubernetes/helm/pkg/chart"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v2"
)
)
// RepoFile represents the .repositories file in $HELM_HOME
var
indexPath
=
"index.yaml"
// ChartRepository represents a chart repository
type
ChartRepository
struct
{
RootPath
string
URL
string
// URL of repository
ChartPaths
[]
string
IndexFile
*
IndexFile
}
// IndexFile represents the index file in a chart repository
type
IndexFile
struct
{
Entries
map
[
string
]
*
ChartRef
}
// ChartRef represents a chart entry in the IndexFile
type
ChartRef
struct
{
Name
string
`yaml:"name"`
URL
string
`yaml:"url"`
Created
string
`yaml:"created,omitempty"`
Removed
bool
`yaml:"removed,omitempty"`
Chartfile
chart
.
Chartfile
`yaml:"chartfile"`
}
// RepoFile represents the repositories.yaml file in $HELM_HOME
type
RepoFile
struct
{
type
RepoFile
struct
{
Repositories
map
[
string
]
string
Repositories
map
[
string
]
string
}
}
...
@@ -38,3 +67,127 @@ func (rf *RepoFile) UnmarshalYAML(unmarshal func(interface{}) error) error {
...
@@ -38,3 +67,127 @@ func (rf *RepoFile) UnmarshalYAML(unmarshal func(interface{}) error) error {
rf
.
Repositories
=
repos
rf
.
Repositories
=
repos
return
nil
return
nil
}
}
// LoadChartRepository takes in a path to a local chart repository
// which contains packaged charts and an index.yaml file
//
// This function evaluates the contents of the directory and
// returns a ChartRepository
func
LoadChartRepository
(
dir
string
)
(
*
ChartRepository
,
error
)
{
dirInfo
,
err
:=
os
.
Stat
(
dir
)
if
err
!=
nil
{
return
nil
,
err
}
if
!
dirInfo
.
IsDir
()
{
return
nil
,
errors
.
New
(
dir
+
"is not a directory"
)
}
r
:=
&
ChartRepository
{
RootPath
:
dir
}
filepath
.
Walk
(
dir
,
func
(
path
string
,
f
os
.
FileInfo
,
err
error
)
error
{
if
!
f
.
IsDir
()
{
if
strings
.
Contains
(
f
.
Name
(),
"index.yaml"
)
{
i
,
err
:=
LoadIndexFile
(
path
)
if
err
!=
nil
{
return
nil
}
r
.
IndexFile
=
i
}
else
{
// TODO: check for tgz extension
r
.
ChartPaths
=
append
(
r
.
ChartPaths
,
path
)
}
}
return
nil
})
return
r
,
nil
}
// UnmarshalYAML unmarshals the index file
func
(
i
*
IndexFile
)
UnmarshalYAML
(
unmarshal
func
(
interface
{})
error
)
error
{
var
refs
map
[
string
]
*
ChartRef
if
err
:=
unmarshal
(
&
refs
);
err
!=
nil
{
if
_
,
ok
:=
err
.
(
*
yaml
.
TypeError
);
!
ok
{
return
err
}
}
i
.
Entries
=
refs
return
nil
}
func
(
i
*
IndexFile
)
addEntry
(
name
string
,
url
string
)
([]
byte
,
error
)
{
if
i
.
Entries
==
nil
{
i
.
Entries
=
make
(
map
[
string
]
*
ChartRef
)
}
entry
:=
ChartRef
{
Name
:
name
,
URL
:
url
}
i
.
Entries
[
name
]
=
&
entry
out
,
err
:=
yaml
.
Marshal
(
&
i
.
Entries
)
if
err
!=
nil
{
return
nil
,
err
}
return
out
,
nil
}
// LoadIndexFile takes a file at the given path and returns an IndexFile object
func
LoadIndexFile
(
path
string
)
(
*
IndexFile
,
error
)
{
b
,
err
:=
ioutil
.
ReadFile
(
path
)
if
err
!=
nil
{
return
nil
,
err
}
var
indexfile
IndexFile
err
=
yaml
.
Unmarshal
(
b
,
&
indexfile
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
indexfile
,
nil
}
func
(
r
*
ChartRepository
)
Index
()
error
{
if
r
.
IndexFile
==
nil
{
r
.
IndexFile
=
&
IndexFile
{
Entries
:
make
(
map
[
string
]
*
ChartRef
)}
}
for
_
,
path
:=
range
r
.
ChartPaths
{
ch
,
err
:=
chart
.
Load
(
path
)
if
err
!=
nil
{
return
err
}
chartfile
:=
ch
.
Chartfile
()
key
:=
chartfile
.
Name
+
"-"
+
chartfile
.
Version
if
r
.
IndexFile
.
Entries
==
nil
{
r
.
IndexFile
.
Entries
=
make
(
map
[
string
]
*
ChartRef
)
}
entry
:=
&
ChartRef
{
Chartfile
:
*
chartfile
,
Name
:
chartfile
.
Name
,
URL
:
""
,
Created
:
""
,
Removed
:
false
}
//TODO: generate hash of contents of chart and add to the entry
//TODO: Set created timestamp
r
.
IndexFile
.
Entries
[
key
]
=
entry
}
if
err
:=
r
.
saveIndexFile
();
err
!=
nil
{
return
err
}
return
nil
}
func
(
r
*
ChartRepository
)
saveIndexFile
()
error
{
index
,
err
:=
yaml
.
Marshal
(
&
r
.
IndexFile
.
Entries
)
if
err
!=
nil
{
return
err
}
if
err
=
ioutil
.
WriteFile
(
filepath
.
Join
(
r
.
RootPath
,
indexPath
),
index
,
0644
);
err
!=
nil
{
return
err
}
return
nil
}
pkg/repo/repo_test.go
0 → 100644
View file @
4bb36c89
package
repo
import
(
"os"
"path/filepath"
"reflect"
"testing"
)
const
testfile
=
"testdata/local-index.yaml"
const
testRepositoriesFile
=
"testdata/repositories.yaml"
const
testRepository
=
"testdata/repository"
func
TestLoadIndexFile
(
t
*
testing
.
T
)
{
cf
,
err
:=
LoadIndexFile
(
testfile
)
if
err
!=
nil
{
t
.
Errorf
(
"Failed to load index file: %s"
,
err
)
}
if
len
(
cf
.
Entries
)
!=
2
{
t
.
Errorf
(
"Expected 2 entries in the index file, but got %d"
,
len
(
cf
.
Entries
))
}
nginx
:=
false
alpine
:=
false
for
k
,
e
:=
range
cf
.
Entries
{
if
k
==
"nginx-0.1.0"
{
if
e
.
Name
==
"nginx"
{
if
len
(
e
.
Chartfile
.
Keywords
)
==
3
{
nginx
=
true
}
}
}
if
k
==
"alpine-1.0.0"
{
if
e
.
Name
==
"alpine"
{
if
len
(
e
.
Chartfile
.
Keywords
)
==
4
{
alpine
=
true
}
}
}
}
if
!
nginx
{
t
.
Errorf
(
"nginx entry was not decoded properly"
)
}
if
!
alpine
{
t
.
Errorf
(
"alpine entry was not decoded properly"
)
}
}
func
TestLoadRepositoriesFile
(
t
*
testing
.
T
)
{
rf
,
err
:=
LoadRepositoriesFile
(
testRepositoriesFile
)
if
err
!=
nil
{
t
.
Errorf
(
testRepositoriesFile
+
" could not be loaded: "
+
err
.
Error
())
}
expected
:=
map
[
string
]
string
{
"best-charts-ever"
:
"http://best-charts-ever.com"
,
"okay-charts"
:
"http://okay-charts.org"
,
"example123"
:
"http://examplecharts.net/charts/123"
}
numOfRepositories
:=
len
(
rf
.
Repositories
)
expectedNumOfRepositories
:=
3
if
numOfRepositories
!=
expectedNumOfRepositories
{
t
.
Errorf
(
"Expected %v repositories but only got %v"
,
expectedNumOfRepositories
,
numOfRepositories
)
}
for
expectedRepo
,
expectedURL
:=
range
expected
{
actual
,
ok
:=
rf
.
Repositories
[
expectedRepo
]
if
!
ok
{
t
.
Errorf
(
"Expected repository: %v but was not found"
,
expectedRepo
)
}
if
expectedURL
!=
actual
{
t
.
Errorf
(
"Expected url %s for the %s repository but got %s "
,
expectedURL
,
expectedRepo
,
actual
)
}
}
}
func
TestLoadChartRepository
(
t
*
testing
.
T
)
{
cr
,
err
:=
LoadChartRepository
(
testRepository
)
if
err
!=
nil
{
t
.
Errorf
(
"Problem loading chart repository from %s: %v"
,
testRepository
,
err
)
}
paths
:=
[]
string
{
filepath
.
Join
(
testRepository
,
"frobnitz-1.2.3.tgz"
),
filepath
.
Join
(
testRepository
,
"sprocket-1.2.0.tgz"
)}
if
cr
.
RootPath
!=
testRepository
{
t
.
Errorf
(
"Expected %s as RootPath but got %s"
,
testRepository
,
cr
.
RootPath
)
}
if
!
reflect
.
DeepEqual
(
cr
.
ChartPaths
,
paths
)
{
t
.
Errorf
(
"Expected %#v but got %#v
\n
"
,
paths
,
cr
.
ChartPaths
)
}
}
func
TestIndex
(
t
*
testing
.
T
)
{
cr
,
err
:=
LoadChartRepository
(
testRepository
)
if
err
!=
nil
{
t
.
Errorf
(
"Problem loading chart repository from %s: %v"
,
testRepository
,
err
)
}
err
=
cr
.
Index
()
if
err
!=
nil
{
t
.
Errorf
(
"Error performing index: %v
\n
"
,
err
)
}
tempIndexPath
:=
filepath
.
Join
(
testRepository
,
indexPath
)
actual
,
err
:=
LoadIndexFile
(
tempIndexPath
)
if
err
!=
nil
{
t
.
Errorf
(
"Error loading index file %v"
,
err
)
}
numEntries
:=
len
(
actual
.
Entries
)
if
numEntries
!=
2
{
t
.
Errorf
(
"Expected 2 charts to be listed in index file but got %v"
,
numEntries
)
}
os
.
Remove
(
tempIndexPath
)
// clean up
}
pkg/repo/testdata/local-index.yaml
View file @
4bb36c89
nginx-0.1.0
:
nginx-0.1.0
:
url
:
http://storage.googleapis.com/kubernetes-charts/nginx-0.1.0.tgz
url
:
http://storage.googleapis.com/kubernetes-charts/nginx-0.1.0.tgz
name
:
nginx
name
:
nginx
description
:
string
chartfile
:
version
:
0.1.0
name
:
nginx
home
:
https://github.com/something
description
:
string
keywords
:
version
:
0.1.0
-
popular
home
:
https://github.com/something
-
web server
keywords
:
-
proxy
-
popular
-
web server
-
proxy
alpine-1.0.0
:
alpine-1.0.0
:
url
:
http://storage.googleapis.com/kubernetes-charts/alpine-1.0.0.tgz
url
:
http://storage.googleapis.com/kubernetes-charts/alpine-1.0.0.tgz
name
:
alpine
name
:
alpine
description
:
string
chartfile
:
version
:
1.0.0
name
:
alpine
home
:
https://github.com/something
description
:
string
keywords
:
version
:
1.0.0
-
linux
home
:
https://github.com/something
-
alpine
keywords
:
-
small
-
linux
-
sumtin
-
alpine
-
small
-
sumtin
pkg/repo/testdata/repositories.yaml
0 → 100644
View file @
4bb36c89
best-charts-ever
:
http://best-charts-ever.com
okay-charts
:
http://okay-charts.org
example123
:
http://examplecharts.net/charts/123
pkg/repo/testdata/repository/frobnitz-1.2.3.tgz
0 → 100644
View file @
4bb36c89
File added
pkg/repo/testdata/repository/sprocket-1.2.0.tgz
0 → 100644
View file @
4bb36c89
File added
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment