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
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
65 additions
and
132 deletions
+65
-132
Makefile
Makefile
+2
-2
deploy.go
cmd/helm/deploy.go
+40
-99
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
$(PATH_WITH_HELM)
go
test
-v
-cover
$
(
addprefix ./,
$(GO_PACKAGES)
)
test-style
:
@
if
[
$(
shell
gofmt
-e
-l
-s
*
.go
$(GO_PACKAGES))
]
;
then
\
echo
"gofmt check failed:"
;
gofmt
-e
-
l
-s
*
.go
$(GO_PACKAGES)
;
exit
1
;
\
@
if
[
$(
shell
gofmt
-e
-l
-s
$(GO_PACKAGES))
]
;
then
\
echo
"gofmt check failed:"
;
gofmt
-e
-
d
-s
$(GO_PACKAGES)
;
exit
1
;
\
fi
@
for
i
in
.
$(GO_PACKAGES)
;
do
\
golint
$$
i
;
\
...
...
cmd/helm/deploy.go
View file @
0bbde9ad
package
main
import
(
"errors"
"fmt"
"os"
"regexp"
"strings"
"io/ioutil"
"github.com/aokoli/goutils"
"github.com/codegangsta/cli"
dep
"github.com/deis/helm-dm/deploy"
"github.com/deis/helm-dm/format"
"github.com/kubernetes/deployment-manager/chart"
"github.com/kubernetes/deployment-manager/common"
"gopkg.in/yaml.v2"
)
func
init
()
{
...
...
@@ -29,9 +23,9 @@ func deployCmd() cli.Command {
Name
:
"dry-run"
,
Usage
:
"Only display the underlying kubectl commands."
,
},
cli
.
Bool
Flag
{
Name
:
"
stdin,i
"
,
Usage
:
"
Read a configuration from STDIN
."
,
cli
.
String
Flag
{
Name
:
"
config,c
"
,
Usage
:
"
The configuration YAML file for this deployment
."
,
},
cli
.
StringFlag
{
Name
:
"name"
,
...
...
@@ -42,110 +36,57 @@ func deployCmd() cli.Command {
Name
:
"properties,p"
,
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
{
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
err
!=
nil
{
format
.
Err
(
"Failed to parse properties: %s"
,
err
)
os
.
Exit
(
1
)
}
d
:=
&
dep
.
Deployment
{
Name
:
c
.
String
(
"Name"
),
Properties
:
props
,
Filename
:
args
[
0
],
Imports
:
args
[
1
:
],
Repository
:
c
.
String
(
"repository"
),
// If there is a configuration file, use it.
cfg
:=
&
common
.
Configuration
{}
if
c
.
String
(
"config"
)
!=
""
{
if
err
:=
loadConfig
(
cfg
,
c
.
String
(
"config"
));
err
!=
nil
{
return
err
}
}
else
{
cfg
.
Resources
=
[]
*
common
.
Resource
{
{
Properties
:
map
[
string
]
interface
{}{},
},
}
}
if
c
.
Bool
(
"stdin"
)
{
d
.
Input
=
os
.
Stdin
// If there is a chart specified on the commandline, override the config
// file with it.
args
:=
c
.
Args
()
if
len
(
args
)
>
0
{
cfg
.
Resources
[
0
]
.
Type
=
args
[
0
]
}
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."
)
// Override the name if one is passed in.
if
name
:=
c
.
String
(
"name"
);
len
(
name
)
>
0
{
cfg
.
Resources
[
0
]
.
Name
=
name
}
fi
,
err
:=
os
.
Stat
(
cfg
.
Filename
)
if
err
!=
nil
{
if
props
,
err
:=
parseProperties
(
c
.
String
(
"properties"
));
err
!=
nil
{
return
err
}
if
fi
.
IsDir
()
{
format
.
Info
(
"Chart is directory"
)
c
,
err
:=
chart
.
LoadDir
(
cfg
.
Filename
)
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
// 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
}
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"
)
{
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
)
return
client
(
c
)
.
PostDeployment
(
cfg
)
}
func
parseTarName
(
name
string
)
(
string
,
string
,
error
)
{
tnregexp
:=
regexp
.
MustCompile
(
chart
.
TarNameRegex
)
if
strings
.
HasSuffix
(
name
,
".tgz"
)
{
name
=
strings
.
TrimSuffix
(
name
,
".tgz"
)
}
v
:=
tnregexp
.
FindStringSubmatch
(
name
)
if
v
==
nil
{
return
name
,
""
,
fmt
.
Errorf
(
"invalid name %s"
,
name
)
// loadConfig loads a file into a common.Configuration.
func
loadConfig
(
c
*
common
.
Configuration
,
filename
string
)
error
{
data
,
err
:=
ioutil
.
ReadFile
(
filename
)
if
err
!=
nil
{
return
err
}
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) {
return
l
,
nil
}
//
Deploy
Chart sends a chart to DM for deploying.
func
(
c
*
Client
)
Deploy
Chart
(
filename
,
deployname
string
)
error
{
//
Upload
Chart sends a chart to DM for deploying.
func
(
c
*
Client
)
Post
Chart
(
filename
,
deployname
string
)
error
{
f
,
err
:=
os
.
Open
(
filename
)
if
err
!=
nil
{
return
err
}
u
,
err
:=
c
.
url
(
"/v2/
deploymen
ts"
)
u
,
err
:=
c
.
url
(
"/v2/
char
ts"
)
request
,
err
:=
http
.
NewRequest
(
"POST"
,
u
,
f
)
if
err
!=
nil
{
f
.
Close
()
...
...
@@ -239,3 +239,7 @@ func (c *Client) DeleteDeployment(name string) (*common.Deployment, error) {
}
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
import
(
"
io/ioutil
"
"
fmt
"
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"
...
...
@@ -133,39 +132,28 @@ func TestGetDeployment(t *testing.T) {
}
}
func
TestDeployChart
(
t
*
testing
.
T
)
{
testfile
:=
"../testdata/charts/frobnitz-0.0.1.tgz"
testname
:=
"sparkles"
fi
,
err
:=
os
.
Stat
(
testfile
)
if
err
!=
nil
{
t
.
Fatalf
(
"could not stat file %s: %s"
,
testfile
,
err
)
func
TestPostDeployment
(
t
*
testing
.
T
)
{
cfg
:=
&
common
.
Configuration
{
[]
*
common
.
Resource
{
{
Name
:
"foo"
,
Type
:
"helm:example.com/foo/bar"
,
Properties
:
map
[
string
]
interface
{}{
"port"
:
":8080"
,
},
},
},
}
expectedSize
:=
int
(
fi
.
Size
())
fc
:=
&
fakeClient
{
handler
:
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
data
,
err
:=
ioutil
.
ReadAll
(
r
.
Body
)
if
err
!=
nil
{
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
)
w
.
WriteHeader
(
http
.
StatusCreated
)
fmt
.
Fprintln
(
w
,
"{}"
)
}),
}
defer
fc
.
teardown
()
if
err
:=
fc
.
setup
()
.
DeployChart
(
testfile
,
testname
);
err
!=
nil
{
t
.
Fatal
(
err
)
if
err
:=
fc
.
setup
()
.
PostDeployment
(
cfg
);
err
!=
nil
{
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