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
5517d00a
Commit
5517d00a
authored
Nov 23, 2016
by
Matt Butcher
Committed by
GitHub
Nov 23, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1547 from technosophos/feat/packs
feat(helm): support 'helm create --starter=mypack'
parents
f637e079
784a3396
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
282 additions
and
4 deletions
+282
-4
create.go
cmd/helm/create.go
+13
-2
create_test.go
cmd/helm/create_test.go
+92
-0
helm_test.go
cmd/helm/helm_test.go
+1
-1
helmhome.go
cmd/helm/helmpath/helmhome.go
+5
-0
helmhome_test.go
cmd/helm/helmpath/helmhome_test.go
+1
-0
init.go
cmd/helm/init.go
+1
-1
charts.md
docs/charts.md
+18
-0
create.go
pkg/chartutil/create.go
+11
-0
create_test.go
pkg/chartutil/create_test.go
+51
-0
save.go
pkg/chartutil/save.go
+55
-0
save_test.go
pkg/chartutil/save_test.go
+34
-0
No files found.
cmd/helm/create.go
View file @
5517d00a
...
...
@@ -24,6 +24,7 @@ import (
"github.com/spf13/cobra"
"k8s.io/helm/cmd/helm/helmpath"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/proto/hapi/chart"
)
...
...
@@ -54,8 +55,10 @@ will be overwritten, but other files will be left alone.
`
type
createCmd
struct
{
name
string
out
io
.
Writer
home
helmpath
.
Home
name
string
out
io
.
Writer
starter
string
}
func
newCreateCmd
(
out
io
.
Writer
)
*
cobra
.
Command
{
...
...
@@ -68,6 +71,7 @@ func newCreateCmd(out io.Writer) *cobra.Command {
Short
:
"create a new chart with the given name"
,
Long
:
createDesc
,
RunE
:
func
(
cmd
*
cobra
.
Command
,
args
[]
string
)
error
{
cc
.
home
=
helmpath
.
Home
(
homePath
())
if
len
(
args
)
==
0
{
return
errors
.
New
(
"the name of the new chart is required"
)
}
...
...
@@ -76,6 +80,7 @@ func newCreateCmd(out io.Writer) *cobra.Command {
},
}
cmd
.
Flags
()
.
StringVarP
(
&
cc
.
starter
,
"starter"
,
"p"
,
""
,
"the named Helm starter scaffold"
)
return
cmd
}
...
...
@@ -90,6 +95,12 @@ func (c *createCmd) run() error {
ApiVersion
:
chartutil
.
ApiVersionV1
,
}
if
c
.
starter
!=
""
{
// Create from the starter
lstarter
:=
filepath
.
Join
(
c
.
home
.
Starters
(),
c
.
starter
)
return
chartutil
.
CreateFrom
(
cfile
,
filepath
.
Dir
(
c
.
name
),
lstarter
)
}
_
,
err
:=
chartutil
.
Create
(
cfile
,
filepath
.
Dir
(
c
.
name
))
return
err
}
cmd/helm/create_test.go
View file @
5517d00a
...
...
@@ -19,9 +19,11 @@ package main
import
(
"io/ioutil"
"os"
"path/filepath"
"testing"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/proto/hapi/chart"
)
func
TestCreateCmd
(
t
*
testing
.
T
)
{
...
...
@@ -69,3 +71,93 @@ func TestCreateCmd(t *testing.T) {
t
.
Errorf
(
"Wrong API version: %q"
,
c
.
Metadata
.
ApiVersion
)
}
}
func
TestCreateStarterCmd
(
t
*
testing
.
T
)
{
cname
:=
"testchart"
// Make a temp dir
tdir
,
err
:=
ioutil
.
TempDir
(
""
,
"helm-create-"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
os
.
Remove
(
tdir
)
thome
,
err
:=
tempHelmHome
(
t
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
old
:=
homePath
()
helmHome
=
thome
defer
func
()
{
helmHome
=
old
os
.
RemoveAll
(
thome
)
}()
// Create a starter.
starterchart
:=
filepath
.
Join
(
thome
,
"starters"
)
os
.
Mkdir
(
starterchart
,
0755
)
if
dest
,
err
:=
chartutil
.
Create
(
&
chart
.
Metadata
{
Name
:
"starterchart"
},
starterchart
);
err
!=
nil
{
t
.
Fatalf
(
"Could not create chart: %s"
,
err
)
}
else
{
t
.
Logf
(
"Created %s"
,
dest
)
}
tplpath
:=
filepath
.
Join
(
starterchart
,
"starterchart"
,
"templates"
,
"foo.tpl"
)
if
err
:=
ioutil
.
WriteFile
(
tplpath
,
[]
byte
(
"test"
),
0755
);
err
!=
nil
{
t
.
Fatalf
(
"Could not write template: %s"
,
err
)
}
// CD into it
pwd
,
err
:=
os
.
Getwd
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
err
:=
os
.
Chdir
(
tdir
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
os
.
Chdir
(
pwd
)
// Run a create
cmd
:=
newCreateCmd
(
os
.
Stdout
)
cmd
.
ParseFlags
([]
string
{
"--starter"
,
"starterchart"
})
if
err
:=
cmd
.
RunE
(
cmd
,
[]
string
{
cname
});
err
!=
nil
{
t
.
Errorf
(
"Failed to run create: %s"
,
err
)
return
}
// Test that the chart is there
if
fi
,
err
:=
os
.
Stat
(
cname
);
err
!=
nil
{
t
.
Fatalf
(
"no chart directory: %s"
,
err
)
}
else
if
!
fi
.
IsDir
()
{
t
.
Fatalf
(
"chart is not directory"
)
}
c
,
err
:=
chartutil
.
LoadDir
(
cname
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
c
.
Metadata
.
Name
!=
cname
{
t
.
Errorf
(
"Expected %q name, got %q"
,
cname
,
c
.
Metadata
.
Name
)
}
if
c
.
Metadata
.
ApiVersion
!=
chartutil
.
ApiVersionV1
{
t
.
Errorf
(
"Wrong API version: %q"
,
c
.
Metadata
.
ApiVersion
)
}
if
l
:=
len
(
c
.
Templates
);
l
!=
5
{
t
.
Errorf
(
"Expected 5 templates, got %d"
,
l
)
}
found
:=
false
for
_
,
tpl
:=
range
c
.
Templates
{
if
tpl
.
Name
==
"templates/foo.tpl"
{
found
=
true
data
:=
tpl
.
Data
if
string
(
data
)
!=
"test"
{
t
.
Errorf
(
"Expected template 'test', got %q"
,
string
(
data
))
}
}
}
if
!
found
{
t
.
Error
(
"Did not find foo.tpl"
)
}
}
cmd/helm/helm_test.go
View file @
5517d00a
...
...
@@ -241,7 +241,7 @@ func tempHelmHome(t *testing.T) (string, error) {
//
// t is used only for logging.
func
ensureTestHome
(
home
helmpath
.
Home
,
t
*
testing
.
T
)
error
{
configDirectories
:=
[]
string
{
home
.
String
(),
home
.
Repository
(),
home
.
Cache
(),
home
.
LocalRepository
()}
configDirectories
:=
[]
string
{
home
.
String
(),
home
.
Repository
(),
home
.
Cache
(),
home
.
LocalRepository
()
,
home
.
Starters
()
}
for
_
,
p
:=
range
configDirectories
{
if
fi
,
err
:=
os
.
Stat
(
p
);
err
!=
nil
{
if
err
:=
os
.
MkdirAll
(
p
,
0755
);
err
!=
nil
{
...
...
cmd/helm/helmpath/helmhome.go
View file @
5517d00a
...
...
@@ -53,6 +53,11 @@ func (h Home) CacheIndex(name string) string {
return
filepath
.
Join
(
string
(
h
),
target
)
}
// Starters returns the path to the Helm starter packs.
func
(
h
Home
)
Starters
()
string
{
return
filepath
.
Join
(
string
(
h
),
"starters"
)
}
// LocalRepository returns the location to the local repo.
//
// The local repo is the one used by 'helm serve'
...
...
cmd/helm/helmpath/helmhome_test.go
View file @
5517d00a
...
...
@@ -33,4 +33,5 @@ func TestHelmHome(t *testing.T) {
isEq
(
t
,
hh
.
LocalRepository
(),
"/r/repository/local"
)
isEq
(
t
,
hh
.
Cache
(),
"/r/repository/cache"
)
isEq
(
t
,
hh
.
CacheIndex
(
"t"
),
"/r/repository/cache/t-index.yaml"
)
isEq
(
t
,
hh
.
Starters
(),
"/r/starters"
)
}
cmd/helm/init.go
View file @
5517d00a
...
...
@@ -143,7 +143,7 @@ func (i *initCmd) run() error {
//
// If $HELM_HOME does not exist, this function will create it.
func
ensureHome
(
home
helmpath
.
Home
,
out
io
.
Writer
)
error
{
configDirectories
:=
[]
string
{
home
.
String
(),
home
.
Repository
(),
home
.
Cache
(),
home
.
LocalRepository
()}
configDirectories
:=
[]
string
{
home
.
String
(),
home
.
Repository
(),
home
.
Cache
(),
home
.
LocalRepository
()
,
home
.
Starters
()
}
for
_
,
p
:=
range
configDirectories
{
if
fi
,
err
:=
os
.
Stat
(
p
);
err
!=
nil
{
fmt
.
Fprintf
(
out
,
"Creating %s
\n
"
,
p
)
...
...
docs/charts.md
View file @
5517d00a
...
...
@@ -543,3 +543,21 @@ commands. However, Helm does not provide tools for uploading charts to
remote repository servers. This is because doing so would add
substantial requirements to an implementing server, and thus raise the
barrier for setting up a repository.
## Chart Starter Packs
The
`helm create`
command takes an optional
`--starter`
option that lets you
specify a "starter chart".
Starters are just regular charts, but are located in
`$HELM_HOME/starters`
.
As a chart developer, you may author charts that are specifically designed
to be used as starters. Such charts should be designed with the following
considerations in mind:
-
The
`Chart.yaml`
will be overwritten by the genertor.
-
Users will expect to modify such a chart's contents, so documentation
should indicate how users can do so.
Currently the only way to add a chart to
`$HELM_HOME/starters`
is to manually
copy it there. In your chart's documentation, you may want to explain that
process.
pkg/chartutil/create.go
View file @
5517d00a
...
...
@@ -175,6 +175,17 @@ We truncate at 24 chars because some Kubernetes name fields are limited to this
{{- end -}}
`
// CreateFrom creates a new chart, but scaffolds it from the src chart.
func
CreateFrom
(
chartfile
*
chart
.
Metadata
,
dest
string
,
src
string
)
error
{
schart
,
err
:=
Load
(
src
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"could not load %s: %s"
,
src
,
err
)
}
schart
.
Metadata
=
chartfile
return
SaveDir
(
schart
,
dest
)
}
// Create creates a new chart in a directory.
//
// Inside of dir, this will create a directory based on the name of
...
...
pkg/chartutil/create_test.go
View file @
5517d00a
...
...
@@ -75,3 +75,54 @@ func TestCreate(t *testing.T) {
}
}
func
TestCreateFrom
(
t
*
testing
.
T
)
{
tdir
,
err
:=
ioutil
.
TempDir
(
""
,
"helm-"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
os
.
RemoveAll
(
tdir
)
cf
:=
&
chart
.
Metadata
{
Name
:
"foo"
}
srcdir
:=
"./testdata/mariner"
if
err
:=
CreateFrom
(
cf
,
tdir
,
srcdir
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
dir
:=
filepath
.
Join
(
tdir
,
"foo"
)
c
:=
filepath
.
Join
(
tdir
,
cf
.
Name
)
mychart
,
err
:=
LoadDir
(
c
)
if
err
!=
nil
{
t
.
Fatalf
(
"Failed to load newly created chart %q: %s"
,
c
,
err
)
}
if
mychart
.
Metadata
.
Name
!=
"foo"
{
t
.
Errorf
(
"Expected name to be 'foo', got %q"
,
mychart
.
Metadata
.
Name
)
}
for
_
,
d
:=
range
[]
string
{
TemplatesDir
,
ChartsDir
}
{
if
fi
,
err
:=
os
.
Stat
(
filepath
.
Join
(
dir
,
d
));
err
!=
nil
{
t
.
Errorf
(
"Expected %s dir: %s"
,
d
,
err
)
}
else
if
!
fi
.
IsDir
()
{
t
.
Errorf
(
"Expected %s to be a directory."
,
d
)
}
}
for
_
,
f
:=
range
[]
string
{
ChartfileName
,
ValuesfileName
,
"requirements.yaml"
}
{
if
fi
,
err
:=
os
.
Stat
(
filepath
.
Join
(
dir
,
f
));
err
!=
nil
{
t
.
Errorf
(
"Expected %s file: %s"
,
f
,
err
)
}
else
if
fi
.
IsDir
()
{
t
.
Errorf
(
"Expected %s to be a file."
,
f
)
}
}
for
_
,
f
:=
range
[]
string
{
"placeholder.tpl"
}
{
if
fi
,
err
:=
os
.
Stat
(
filepath
.
Join
(
dir
,
TemplatesDir
,
f
));
err
!=
nil
{
t
.
Errorf
(
"Expected %s file: %s"
,
f
,
err
)
}
else
if
fi
.
IsDir
()
{
t
.
Errorf
(
"Expected %s to be a file."
,
f
)
}
}
}
pkg/chartutil/save.go
View file @
5517d00a
...
...
@@ -21,6 +21,7 @@ import (
"compress/gzip"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
...
...
@@ -31,6 +32,60 @@ import (
var
headerBytes
=
[]
byte
(
"+aHR0cHM6Ly95b3V0dS5iZS96OVV6MWljandyTQo="
)
// SaveDir saves a chart as files in a directory.
func
SaveDir
(
c
*
chart
.
Chart
,
dest
string
)
error
{
// Create the chart directory
outdir
:=
filepath
.
Join
(
dest
,
c
.
Metadata
.
Name
)
if
err
:=
os
.
Mkdir
(
outdir
,
0755
);
err
!=
nil
{
return
err
}
// Save the chart file.
if
err
:=
SaveChartfile
(
filepath
.
Join
(
outdir
,
ChartfileName
),
c
.
Metadata
);
err
!=
nil
{
return
err
}
// Save values.yaml
if
c
.
Values
!=
nil
&&
len
(
c
.
Values
.
Raw
)
>
0
{
vf
:=
filepath
.
Join
(
outdir
,
ValuesfileName
)
if
err
:=
ioutil
.
WriteFile
(
vf
,
[]
byte
(
c
.
Values
.
Raw
),
0755
);
err
!=
nil
{
return
err
}
}
for
_
,
d
:=
range
[]
string
{
TemplatesDir
,
ChartsDir
}
{
if
err
:=
os
.
MkdirAll
(
filepath
.
Join
(
outdir
,
d
),
0755
);
err
!=
nil
{
return
err
}
}
// Save templates
for
_
,
f
:=
range
c
.
Templates
{
n
:=
filepath
.
Join
(
outdir
,
f
.
Name
)
if
err
:=
ioutil
.
WriteFile
(
n
,
f
.
Data
,
0755
);
err
!=
nil
{
return
err
}
}
// Save files
for
_
,
f
:=
range
c
.
Files
{
n
:=
filepath
.
Join
(
outdir
,
f
.
TypeUrl
)
if
err
:=
ioutil
.
WriteFile
(
n
,
f
.
Value
,
0755
);
err
!=
nil
{
return
err
}
}
// Save dependencies
base
:=
filepath
.
Join
(
outdir
,
ChartsDir
)
for
_
,
dep
:=
range
c
.
Dependencies
{
// Here, we write each dependency as a tar file.
if
_
,
err
:=
Save
(
dep
,
base
);
err
!=
nil
{
return
err
}
}
return
nil
}
// Save creates an archived chart to the given directory.
//
// This takes an existing chart and a destination directory.
...
...
pkg/chartutil/save_test.go
View file @
5517d00a
...
...
@@ -65,3 +65,37 @@ func TestSave(t *testing.T) {
t
.
Fatal
(
"Values data did not match"
)
}
}
func
TestSaveDir
(
t
*
testing
.
T
)
{
tmp
,
err
:=
ioutil
.
TempDir
(
""
,
"helm-"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
os
.
RemoveAll
(
tmp
)
c
:=
&
chart
.
Chart
{
Metadata
:
&
chart
.
Metadata
{
Name
:
"ahab"
,
Version
:
"1.2.3.4"
,
},
Values
:
&
chart
.
Config
{
Raw
:
"ship: Pequod"
,
},
}
if
err
:=
SaveDir
(
c
,
tmp
);
err
!=
nil
{
t
.
Fatalf
(
"Failed to save: %s"
,
err
)
}
c2
,
err
:=
LoadDir
(
tmp
+
"/ahab"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
c2
.
Metadata
.
Name
!=
c
.
Metadata
.
Name
{
t
.
Fatalf
(
"Expected chart archive to have %q, got %q"
,
c
.
Metadata
.
Name
,
c2
.
Metadata
.
Name
)
}
if
c2
.
Values
.
Raw
!=
c
.
Values
.
Raw
{
t
.
Fatal
(
"Values data did not match"
)
}
}
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