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
4fe37ea6
Commit
4fe37ea6
authored
Feb 02, 2016
by
Matt Butcher
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Save and Create functions.
parent
cfaca7ff
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
337 additions
and
1 deletion
+337
-1
chart.go
chart/chart.go
+65
-0
chartfile.go
chart/chartfile.go
+6
-1
save.go
chart/save.go
+124
-0
save_test.go
chart/save_test.go
+123
-0
Chart.yaml
chart/testdata/sprocket/Chart.yaml
+4
-0
LICENSE
chart/testdata/sprocket/LICENSE
+1
-0
README.md
chart/testdata/sprocket/README.md
+3
-0
README.md
chart/testdata/sprocket/docs/README.md
+1
-0
pre-install.py
chart/testdata/sprocket/hooks/pre-install.py
+1
-0
icon.svg
chart/testdata/sprocket/icon.svg
+8
-0
placeholder.txt
chart/testdata/sprocket/templates/placeholder.txt
+1
-0
No files found.
chart/chart.go
View file @
4fe37ea6
...
...
@@ -39,6 +39,8 @@ const (
preIcon
string
=
"icon.svg"
)
var
headerBytes
=
[]
byte
(
"+aHR0cHM6Ly95b3V0dS5iZS96OVV6MWljandyTQo="
)
// Chart represents a complete chart.
//
// A chart consists of the following parts:
...
...
@@ -146,6 +148,69 @@ func (t *tarChart) close() error {
return
os
.
RemoveAll
(
t
.
tmpDir
)
}
// New creates a new chart in a directory.
//
// Inside of dir, this will create a directory based on the name of
// chartfile.Name. It will then write the Chart.yaml into this directory and
// create the (empty) appropriate directories.
//
// The returned *Chart will point to the newly created directory.
//
// If dir does not exist, this will return an error.
// If Chart.yaml or any directories cannot be created, this will return an
// error. In such a case, this will attempt to clean up by removing the
// new chart directory.
func
Create
(
chartfile
*
Chartfile
,
dir
string
)
(
*
Chart
,
error
)
{
path
,
err
:=
filepath
.
Abs
(
dir
)
if
err
!=
nil
{
return
nil
,
err
}
if
fi
,
err
:=
os
.
Stat
(
path
);
err
!=
nil
{
return
nil
,
err
}
else
if
!
fi
.
IsDir
()
{
return
nil
,
fmt
.
Errorf
(
"no such directory %s"
,
path
)
}
n
:=
fname
(
chartfile
.
Name
)
cdir
:=
filepath
.
Join
(
path
,
n
)
if
_
,
err
:=
os
.
Stat
(
cdir
);
err
==
nil
{
return
nil
,
fmt
.
Errorf
(
"directory already exists: %s"
,
cdir
)
}
if
err
:=
os
.
MkdirAll
(
cdir
,
0755
);
err
!=
nil
{
return
nil
,
err
}
rollback
:=
func
()
{
// TODO: Should we log failures here?
os
.
RemoveAll
(
cdir
)
}
if
err
:=
chartfile
.
Save
(
filepath
.
Join
(
cdir
,
ChartfileName
));
err
!=
nil
{
rollback
()
return
nil
,
err
}
for
_
,
d
:=
range
[]
string
{
preHooks
,
preDocs
,
preTemplates
}
{
if
err
:=
os
.
MkdirAll
(
filepath
.
Join
(
cdir
,
d
),
0755
);
err
!=
nil
{
rollback
()
return
nil
,
err
}
}
return
&
Chart
{
loader
:
&
dirChart
{
chartyaml
:
chartfile
,
chartdir
:
cdir
},
},
nil
}
// fname prepares names for the filesystem
func
fname
(
name
string
)
string
{
// Right now, we don't do anything. Do we need to encode any particular
// characters? What characters are legal in a chart name, but not in file
// names on Windows, Linux, or OSX.
return
name
}
// LoadDir loads an entire chart from a directory.
//
// This includes the Chart.yaml (*Chartfile) and all of the manifests.
...
...
chart/chartfile.go
View file @
4fe37ea6
...
...
@@ -69,7 +69,7 @@ func LoadChartfile(filename string) (*Chartfile, error) {
// Save saves a Chart.yaml file
func
(
c
*
Chartfile
)
Save
(
filename
string
)
error
{
b
,
err
:=
yaml
.
Marshal
(
c
)
b
,
err
:=
c
.
Marshal
(
)
if
err
!=
nil
{
return
err
}
...
...
@@ -77,6 +77,11 @@ func (c *Chartfile) Save(filename string) error {
return
ioutil
.
WriteFile
(
filename
,
b
,
0644
)
}
// Marshal encodes the chart file into YAML.
func
(
c
*
Chartfile
)
Marshal
()
([]
byte
,
error
)
{
return
yaml
.
Marshal
(
c
)
}
// VersionOK returns true if the given version meets the constraints.
//
// It returns false if the version string or constraint is unparsable or if the
...
...
chart/save.go
0 → 100644
View file @
4fe37ea6
/*
Copyright 2015 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
chart
import
(
"archive/tar"
"compress/gzip"
"fmt"
"io"
"os"
"path/filepath"
"github.com/kubernetes/deployment-manager/log"
)
// Save creates an archived chart to the given directory.
//
// This takes an existing chart and a destination directory.
//
// If the directory is /foo, and the chart is named bar, with version 1.0.0, this
// will generate /foo/bar-1.0.0.tgz.
//
// This returns the absolute path to the chart archive file.
func
Save
(
c
*
Chart
,
outDir
string
)
(
string
,
error
)
{
// Create archive
if
fi
,
err
:=
os
.
Stat
(
outDir
);
err
!=
nil
{
return
""
,
err
}
else
if
!
fi
.
IsDir
()
{
return
""
,
fmt
.
Errorf
(
"location %s is not a directory"
,
outDir
)
}
cfile
:=
c
.
Chartfile
()
dir
:=
c
.
Dir
()
basename
:=
filepath
.
Base
(
dir
)
pdir
:=
filepath
.
Dir
(
dir
)
if
basename
==
"."
{
basename
=
fname
(
cfile
.
Name
)
}
filename
:=
fmt
.
Sprintf
(
"%s-%s.tgz"
,
fname
(
cfile
.
Name
),
cfile
.
Version
)
filename
=
filepath
.
Join
(
outDir
,
filename
)
// Fail early if the YAML is borked.
if
err
:=
cfile
.
Save
(
filepath
.
Join
(
dir
,
ChartfileName
));
err
!=
nil
{
return
""
,
err
}
// Create file.
f
,
err
:=
os
.
Create
(
filename
)
if
err
!=
nil
{
return
""
,
err
}
// Wrap in gzip writer
zipper
:=
gzip
.
NewWriter
(
f
)
zipper
.
Header
.
Extra
=
headerBytes
zipper
.
Header
.
Comment
=
"Helm"
// Wrap in tar writer
twriter
:=
tar
.
NewWriter
(
zipper
)
rollback
:=
false
defer
func
()
{
twriter
.
Close
()
zipper
.
Close
()
f
.
Close
()
if
rollback
{
log
.
Warn
(
"Removing incomplete archive %s"
,
filename
)
os
.
Remove
(
filename
)
}
}()
err
=
filepath
.
Walk
(
dir
,
func
(
path
string
,
fi
os
.
FileInfo
,
err
error
)
error
{
if
err
!=
nil
{
return
err
}
hdr
,
err
:=
tar
.
FileInfoHeader
(
fi
,
"."
)
if
err
!=
nil
{
return
err
}
relpath
,
err
:=
filepath
.
Rel
(
pdir
,
path
)
if
err
!=
nil
{
return
err
}
hdr
.
Name
=
relpath
twriter
.
WriteHeader
(
hdr
)
// Skip directories.
if
fi
.
IsDir
()
{
return
nil
}
in
,
err
:=
os
.
Open
(
path
)
if
err
!=
nil
{
return
err
}
_
,
err
=
io
.
Copy
(
twriter
,
in
)
in
.
Close
()
if
err
!=
nil
{
return
err
}
return
nil
})
if
err
!=
nil
{
rollback
=
true
return
filename
,
err
}
return
filename
,
nil
}
chart/save_test.go
0 → 100644
View file @
4fe37ea6
/*
Copyright 2015 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
chart
import
(
"archive/tar"
"compress/gzip"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
)
const
sprocketdir
=
"testdata/sprocket"
func
TestSave
(
t
*
testing
.
T
)
{
tmpdir
,
err
:=
ioutil
.
TempDir
(
""
,
"helm-"
)
if
err
!=
nil
{
t
.
Fatal
(
"Could not create temp directory"
)
}
t
.
Logf
(
"Temp: %s"
,
tmpdir
)
// Because of the defer, don't call t.Fatal in the remainder of this
// function.
defer
os
.
RemoveAll
(
tmpdir
)
c
,
err
:=
LoadDir
(
sprocketdir
)
if
err
!=
nil
{
t
.
Errorf
(
"Failed to load %s: %s"
,
sprocketdir
,
err
)
return
}
tfile
,
err
:=
Save
(
c
,
tmpdir
)
if
err
!=
nil
{
t
.
Errorf
(
"Failed to save %s to %s: %s"
,
c
.
Chartfile
()
.
Name
,
tmpdir
,
err
)
return
}
b
:=
filepath
.
Base
(
tfile
)
expectname
:=
"sprocket-1.2.3-alpha.1+12345.tgz"
if
b
!=
expectname
{
t
.
Errorf
(
"Expected %q, got %q"
,
expectname
,
b
)
}
files
,
err
:=
getAllFiles
(
tfile
)
if
err
!=
nil
{
t
.
Errorf
(
"Could not extract files: %s"
,
err
)
}
// Files should come back in order.
expect
:=
[]
string
{
"sprocket"
,
"sprocket/Chart.yaml"
,
"sprocket/LICENSE"
,
"sprocket/README.md"
,
"sprocket/docs"
,
"sprocket/docs/README.md"
,
"sprocket/hooks"
,
"sprocket/hooks/pre-install.py"
,
"sprocket/icon.svg"
,
"sprocket/templates"
,
"sprocket/templates/placeholder.txt"
,
}
if
len
(
expect
)
!=
len
(
files
)
{
t
.
Errorf
(
"Expected %d files, found %d"
,
len
(
expect
),
len
(
files
))
return
}
for
i
:=
0
;
i
<
len
(
expect
);
i
++
{
if
expect
[
i
]
!=
files
[
i
]
{
t
.
Errorf
(
"Expected file %q, got %q"
,
expect
[
i
],
files
[
i
])
}
}
}
func
getAllFiles
(
tfile
string
)
([]
string
,
error
)
{
f1
,
err
:=
os
.
Open
(
tfile
)
if
err
!=
nil
{
return
[]
string
{},
err
}
f2
,
err
:=
gzip
.
NewReader
(
f1
)
if
err
!=
nil
{
f1
.
Close
()
return
[]
string
{},
err
}
if
f2
.
Header
.
Comment
!=
"Helm"
{
return
[]
string
{},
fmt
.
Errorf
(
"Expected header Helm. Got %s"
,
f2
.
Header
.
Comment
)
}
if
string
(
f2
.
Header
.
Extra
)
!=
string
(
headerBytes
)
{
return
[]
string
{},
fmt
.
Errorf
(
"Expected header signature. Got %v"
,
f2
.
Header
.
Extra
)
}
f3
:=
tar
.
NewReader
(
f2
)
files
:=
[]
string
{}
var
e
error
var
hdr
*
tar
.
Header
for
e
==
nil
{
hdr
,
e
=
f3
.
Next
()
if
e
==
nil
{
files
=
append
(
files
,
hdr
.
Name
)
}
}
f2
.
Close
()
f1
.
Close
()
return
files
,
nil
}
chart/testdata/sprocket/Chart.yaml
0 → 100644
View file @
4fe37ea6
name
:
sprocket
description
:
This is a sprocket.
version
:
1.2.3-alpha.1+12345
home
:
"
"
chart/testdata/sprocket/LICENSE
0 → 100644
View file @
4fe37ea6
Placeholder for license.
chart/testdata/sprocket/README.md
0 → 100644
View file @
4fe37ea6
# Sprocket
This is an example chart.
chart/testdata/sprocket/docs/README.md
0 → 100644
View file @
4fe37ea6
This is a placeholder for documentation.
chart/testdata/sprocket/hooks/pre-install.py
0 → 100644
View file @
4fe37ea6
# Placeholder.
chart/testdata/sprocket/icon.svg
0 → 100644
View file @
4fe37ea6
<?xml version="1.0"?>
<svg
xmlns:svg=
"http://www.w3.org/2000/svg"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
version=
"1.0"
width=
"256"
height=
"256"
id=
"test"
>
<desc>
Example icon
</desc>
<rect
id=
"first"
x=
"2"
y=
"2"
width=
"40"
height=
"60"
fill=
"navy"
/>
<rect
id=
"second"
x=
"15"
y=
"4"
width=
"40"
height=
"60"
fill=
"red"
/>
</svg>
chart/testdata/sprocket/templates/placeholder.txt
0 → 100644
View file @
4fe37ea6
This is a placeholder.
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