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
0bbde9ad
Commit
0bbde9ad
authored
Feb 24, 2016
by
Matt Butcher
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #23 from technosophos/feat/deploy
Implement client side of `helm deploy`
parents
a0acb3d5
436b7f03
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
63 additions
and
130 deletions
+63
-130
Makefile
Makefile
+2
-2
deploy.go
cmd/helm/deploy.go
+38
-97
client.go
dm/client.go
+7
-3
client_test.go
dm/client_test.go
+16
-28
No files found.
Makefile
View file @
0bbde9ad
...
@@ -50,8 +50,8 @@ test: test-style
...
@@ -50,8 +50,8 @@ test: test-style
$(PATH_WITH_HELM)
go
test
-v
-cover
$
(
addprefix ./,
$(GO_PACKAGES)
)
$(PATH_WITH_HELM)
go
test
-v
-cover
$
(
addprefix ./,
$(GO_PACKAGES)
)
test-style
:
test-style
:
@
if
[
$(
shell
gofmt
-e
-l
-s
*
.go
$(GO_PACKAGES))
]
;
then
\
@
if
[
$(
shell
gofmt
-e
-l
-s
$(GO_PACKAGES))
]
;
then
\
echo
"gofmt check failed:"
;
gofmt
-e
-
l
-s
*
.go
$(GO_PACKAGES)
;
exit
1
;
\
echo
"gofmt check failed:"
;
gofmt
-e
-
d
-s
$(GO_PACKAGES)
;
exit
1
;
\
fi
fi
@
for
i
in
.
$(GO_PACKAGES)
;
do
\
@
for
i
in
.
$(GO_PACKAGES)
;
do
\
golint
$$
i
;
\
golint
$$
i
;
\
...
...
cmd/helm/deploy.go
View file @
0bbde9ad
package
main
package
main
import
(
import
(
"errors"
"io/ioutil"
"fmt"
"os"
"regexp"
"strings"
"github.com/aokoli/goutils"
"github.com/codegangsta/cli"
"github.com/codegangsta/cli"
dep
"github.com/deis/helm-dm/deploy"
"github.com/kubernetes/deployment-manager/common"
"github.com/deis/helm-dm/format"
"gopkg.in/yaml.v2"
"github.com/kubernetes/deployment-manager/chart"
)
)
func
init
()
{
func
init
()
{
...
@@ -29,9 +23,9 @@ func deployCmd() cli.Command {
...
@@ -29,9 +23,9 @@ func deployCmd() cli.Command {
Name
:
"dry-run"
,
Name
:
"dry-run"
,
Usage
:
"Only display the underlying kubectl commands."
,
Usage
:
"Only display the underlying kubectl commands."
,
},
},
cli
.
Bool
Flag
{
cli
.
String
Flag
{
Name
:
"
stdin,i
"
,
Name
:
"
config,c
"
,
Usage
:
"
Read a configuration from STDIN
."
,
Usage
:
"
The configuration YAML file for this deployment
."
,
},
},
cli
.
StringFlag
{
cli
.
StringFlag
{
Name
:
"name"
,
Name
:
"name"
,
...
@@ -42,110 +36,57 @@ func deployCmd() cli.Command {
...
@@ -42,110 +36,57 @@ func deployCmd() cli.Command {
Name
:
"properties,p"
,
Name
:
"properties,p"
,
Usage
:
"A comma-separated list of key=value pairs: 'foo=bar,foo2=baz'."
,
Usage
:
"A comma-separated list of key=value pairs: 'foo=bar,foo2=baz'."
,
},
},
cli
.
StringFlag
{
// FIXME: This is not right. It's sort of a half-baked forward
// port of dm.go.
Name
:
"repository"
,
Usage
:
"The default repository"
,
Value
:
"kubernetes/application-dm-templates"
,
},
},
},
}
}
}
}
func
deploy
(
c
*
cli
.
Context
)
error
{
func
deploy
(
c
*
cli
.
Context
)
error
{
args
:=
c
.
Args
()
if
len
(
args
)
<
1
{
format
.
Err
(
"First argument, filename, is required. Try 'helm deploy --help'"
)
os
.
Exit
(
1
)
}
props
,
err
:=
parseProperties
(
c
.
String
(
"properties"
))
// If there is a configuration file, use it.
if
err
!=
nil
{
cfg
:=
&
common
.
Configuration
{}
format
.
Err
(
"Failed to parse properties: %s"
,
err
)
if
c
.
String
(
"config"
)
!=
""
{
os
.
Exit
(
1
)
if
err
:=
loadConfig
(
cfg
,
c
.
String
(
"config"
));
err
!=
nil
{
}
return
err
d
:=
&
dep
.
Deployment
{
Name
:
c
.
String
(
"Name"
),
Properties
:
props
,
Filename
:
args
[
0
],
Imports
:
args
[
1
:
],
Repository
:
c
.
String
(
"repository"
),
}
}
}
else
{
if
c
.
Bool
(
"stdin"
)
{
cfg
.
Resources
=
[]
*
common
.
Resource
{
d
.
Input
=
os
.
Stdin
{
Properties
:
map
[
string
]
interface
{}{},
},
}
}
return
doDeploy
(
d
,
c
)
}
func
doDeploy
(
cfg
*
dep
.
Deployment
,
cxt
*
cli
.
Context
)
error
{
if
cfg
.
Filename
==
""
{
return
errors
.
New
(
"A filename must be specified. For a tar archive, this is the name of the root template in the archive."
)
}
}
fi
,
err
:=
os
.
Stat
(
cfg
.
Filename
)
// If there is a chart specified on the commandline, override the config
if
err
!=
nil
{
// file with it.
return
err
args
:=
c
.
Args
()
if
len
(
args
)
>
0
{
cfg
.
Resources
[
0
]
.
Type
=
args
[
0
]
}
}
if
fi
.
IsDir
()
{
// Override the name if one is passed in.
format
.
Info
(
"Chart is directory"
)
if
name
:=
c
.
String
(
"name"
);
len
(
name
)
>
0
{
c
,
err
:=
chart
.
LoadDir
(
cfg
.
Filename
)
cfg
.
Resources
[
0
]
.
Name
=
name
if
err
!=
nil
{
return
err
}
if
cfg
.
Name
==
""
{
cfg
.
Name
=
genName
(
c
.
Chartfile
()
.
Name
)
}
}
// TODO: Is it better to generate the file in temp dir like this, or
if
props
,
err
:=
parseProperties
(
c
.
String
(
"properties"
));
err
!=
nil
{
// just put it in the CWD?
//tdir, err := ioutil.TempDir("", "helm-")
//if err != nil {
//format.Warn("Could not create temporary directory. Using .")
//tdir = "."
//} else {
//defer os.RemoveAll(tdir)
//}
tdir
:=
"."
tfile
,
err
:=
chart
.
Save
(
c
,
tdir
)
if
err
!=
nil
{
return
err
return
err
}
else
if
len
(
props
)
>
0
{
// Coalesce the properties into the first props. We have no way of
// knowing which resource the properties are supposed to be part
// of.
for
n
,
v
:=
range
props
{
cfg
.
Resources
[
0
]
.
Properties
[
n
]
=
v
}
}
cfg
.
Filename
=
tfile
}
else
if
cfg
.
Name
==
""
{
n
,
_
,
e
:=
parseTarName
(
cfg
.
Filename
)
if
e
!=
nil
{
return
e
}
cfg
.
Name
=
n
}
}
if
cxt
.
Bool
(
"dry-run"
)
{
return
client
(
c
)
.
PostDeployment
(
cfg
)
format
.
Info
(
"Prepared deploy %q using file %q"
,
cfg
.
Name
,
cfg
.
Filename
)
return
nil
}
c
:=
client
(
cxt
)
return
c
.
DeployChart
(
cfg
.
Filename
,
cfg
.
Name
)
}
func
genName
(
pname
string
)
string
{
s
,
_
:=
goutils
.
RandomAlphaNumeric
(
8
)
return
fmt
.
Sprintf
(
"%s-%s"
,
pname
,
s
)
}
}
func
parseTarName
(
name
string
)
(
string
,
string
,
error
)
{
// loadConfig loads a file into a common.Configuration.
tnregexp
:=
regexp
.
MustCompile
(
chart
.
TarNameRegex
)
func
loadConfig
(
c
*
common
.
Configuration
,
filename
string
)
error
{
if
strings
.
HasSuffix
(
name
,
".tgz"
)
{
data
,
err
:=
ioutil
.
ReadFile
(
filename
)
name
=
strings
.
TrimSuffix
(
name
,
".tgz"
)
if
err
!=
nil
{
}
return
err
v
:=
tnregexp
.
FindStringSubmatch
(
name
)
if
v
==
nil
{
return
name
,
""
,
fmt
.
Errorf
(
"invalid name %s"
,
name
)
}
}
return
v
[
1
],
v
[
2
],
nil
return
yaml
.
Unmarshal
(
data
,
c
)
}
}
dm/client.go
View file @
0bbde9ad
...
@@ -174,14 +174,14 @@ func (c *Client) ListDeployments() ([]string, error) {
...
@@ -174,14 +174,14 @@ func (c *Client) ListDeployments() ([]string, error) {
return
l
,
nil
return
l
,
nil
}
}
//
Deploy
Chart sends a chart to DM for deploying.
//
Upload
Chart sends a chart to DM for deploying.
func
(
c
*
Client
)
Deploy
Chart
(
filename
,
deployname
string
)
error
{
func
(
c
*
Client
)
Post
Chart
(
filename
,
deployname
string
)
error
{
f
,
err
:=
os
.
Open
(
filename
)
f
,
err
:=
os
.
Open
(
filename
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
u
,
err
:=
c
.
url
(
"/v2/
deploymen
ts"
)
u
,
err
:=
c
.
url
(
"/v2/
char
ts"
)
request
,
err
:=
http
.
NewRequest
(
"POST"
,
u
,
f
)
request
,
err
:=
http
.
NewRequest
(
"POST"
,
u
,
f
)
if
err
!=
nil
{
if
err
!=
nil
{
f
.
Close
()
f
.
Close
()
...
@@ -239,3 +239,7 @@ func (c *Client) DeleteDeployment(name string) (*common.Deployment, error) {
...
@@ -239,3 +239,7 @@ func (c *Client) DeleteDeployment(name string) (*common.Deployment, error) {
}
}
return
deployment
,
nil
return
deployment
,
nil
}
}
func
(
c
*
Client
)
PostDeployment
(
cfg
*
common
.
Configuration
)
error
{
return
c
.
CallService
(
"/deployments"
,
"POST"
,
"post deployment"
,
cfg
,
nil
)
}
dm/client_test.go
View file @
0bbde9ad
package
dm
package
dm
import
(
import
(
"
io/ioutil
"
"
fmt
"
"net/http"
"net/http"
"net/http/httptest"
"net/http/httptest"
"os"
"strings"
"strings"
"testing"
"testing"
...
@@ -133,39 +132,28 @@ func TestGetDeployment(t *testing.T) {
...
@@ -133,39 +132,28 @@ func TestGetDeployment(t *testing.T) {
}
}
}
}
func
TestDeployChart
(
t
*
testing
.
T
)
{
func
TestPostDeployment
(
t
*
testing
.
T
)
{
testfile
:=
"../testdata/charts/frobnitz-0.0.1.tgz"
cfg
:=
&
common
.
Configuration
{
testname
:=
"sparkles"
[]
*
common
.
Resource
{
{
fi
,
err
:=
os
.
Stat
(
testfile
)
Name
:
"foo"
,
if
err
!=
nil
{
Type
:
"helm:example.com/foo/bar"
,
t
.
Fatalf
(
"could not stat file %s: %s"
,
testfile
,
err
)
Properties
:
map
[
string
]
interface
{}{
"port"
:
":8080"
,
},
},
},
}
}
expectedSize
:=
int
(
fi
.
Size
())
fc
:=
&
fakeClient
{
fc
:=
&
fakeClient
{
handler
:
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
handler
:
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
data
,
err
:=
ioutil
.
ReadAll
(
r
.
Body
)
w
.
WriteHeader
(
http
.
StatusCreated
)
if
err
!=
nil
{
fmt
.
Fprintln
(
w
,
"{}"
)
t
.
Errorf
(
"Failed to read data off of request: %s"
,
err
)
}
if
len
(
data
)
!=
expectedSize
{
t
.
Errorf
(
"Expected content length %d, got %d"
,
expectedSize
,
len
(
data
))
}
if
cn
:=
r
.
Header
.
Get
(
"x-chart-name"
);
cn
!=
"frobnitz-0.0.1.tgz"
{
t
.
Errorf
(
"Expected frobnitz-0.0.1.tgz, got %q"
,
cn
)
}
if
dn
:=
r
.
Header
.
Get
(
"x-deployment-name"
);
dn
!=
"sparkles"
{
t
.
Errorf
(
"Expected sparkles, got %q"
,
dn
)
}
w
.
WriteHeader
(
201
)
}),
}),
}
}
defer
fc
.
teardown
()
defer
fc
.
teardown
()
if
err
:=
fc
.
setup
()
.
DeployChart
(
testfile
,
testname
);
err
!=
nil
{
if
err
:=
fc
.
setup
()
.
PostDeployment
(
cfg
);
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
f
(
"failed to post deployment: %s"
,
err
)
}
}
}
}
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