Merge pull request #550 from vaikas-google/master

Implement deployment describe
pull/559/head
vaikas-google 9 years ago
commit fab58c7a2b

@ -48,6 +48,13 @@ Status: {{.State.Status}}
{{range .}} {{.}}{{end}}
{{end}}`
const defaultShowResourceFormat = `Name: {{.Name}}
Type: {{.Type}}
Status: {{.State.Status}}
{{with .State.Errors}}Errors:
{{range .}} {{.}}{{end}}
{{end}}`
func init() {
addCommands(deploymentCommands())
}
@ -145,13 +152,23 @@ func describeDeployment(c *cli.Context) error {
return errTooManyArgs
}
name := args[0]
_, err := NewClient(c).DescribeDeployment(name)
manifest, err := NewClient(c).DescribeDeployment(name)
if err != nil {
return err
}
format.Info("TO BE IMPLEMENTED")
if manifest.ExpandedConfig == nil {
return errors.New("No ExpandedConfig found for: " + name)
}
for _, resource := range manifest.ExpandedConfig.Resources {
tmpl := template.Must(template.New("showresource").Parse(defaultShowResourceFormat))
err = tmpl.Execute(os.Stdout, resource)
if err != nil {
return err
}
}
return nil
}

@ -24,45 +24,78 @@ import (
"github.com/kubernetes/helm/pkg/common"
)
type pathAndResponse struct {
path string
resp interface{}
}
func TestDeployment(t *testing.T) {
var deploymentTestCases = []struct {
args []string
resp interface{}
resp []pathAndResponse
expected string
}{
{
[]string{"deployment", "show", "guestbook.yaml"},
&common.Deployment{
[]pathAndResponse{{"/deployments/", &common.Deployment{
Name: "guestbook.yaml",
State: &common.DeploymentState{Status: common.CreatedStatus},
},
}}},
"Name: guestbook.yaml\nStatus: Created\n",
},
{
[]string{"deployment", "show", "guestbook.yaml"},
&common.Deployment{
[]pathAndResponse{{"/deployments/", &common.Deployment{
Name: "guestbook.yaml",
State: &common.DeploymentState{
Status: common.FailedStatus,
Errors: []string{"error message"},
},
},
}}},
"Name: guestbook.yaml\nStatus: Failed\nErrors:\n error message\n",
},
{
[]string{"deployment", "list"},
[]string{"guestbook.yaml"},
[]pathAndResponse{{"/deployments/", []string{"guestbook.yaml"}}},
"guestbook.yaml\n",
},
{
[]string{"deployment", "describe", "guestbook.yaml"},
[]pathAndResponse{{
"/deployments/guestbook.yaml",
&common.Deployment{Name: "guestbook.yaml",
State: &common.DeploymentState{Status: common.CreatedStatus},
LatestManifest: "manifestxyz",
}},
{"/deployments/guestbook.yaml/manifests/manifestxyz", &common.Manifest{
Deployment: "guestbook.yaml",
Name: "manifestxyz",
ExpandedConfig: &common.Configuration{
Resources: []*common.Resource{
{Name: "fe-rc", Type: "ReplicationController", State: &common.ResourceState{Status: common.Created}},
{Name: "fe", Type: "Service", State: &common.ResourceState{Status: common.Created}},
{Name: "be-rc", Type: "ReplicationController", State: &common.ResourceState{Status: common.Created}},
{Name: "be", Type: "Service", State: &common.ResourceState{Status: common.Created}},
},
},
}}},
"Name: fe-rc\nType: ReplicationController\nStatus: Created\n" +
"Name: fe\nType: Service\nStatus: Created\n" +
"Name: be-rc\nType: ReplicationController\nStatus: Created\n" +
"Name: be\nType: Service\nStatus: Created\n",
},
}
for _, tc := range deploymentTestCases {
th := testHelm(t)
th.mux.HandleFunc("/deployments/", func(w http.ResponseWriter, r *http.Request) {
data, err := json.Marshal(tc.resp)
th.must(err)
w.Write(data)
})
for _, pathAndResponse := range tc.resp {
var response = pathAndResponse.resp
th.mux.HandleFunc(pathAndResponse.path, func(w http.ResponseWriter, r *http.Request) {
data, err := json.Marshal(response)
th.must(err)
w.Write(data)
})
}
th.run(tc.args...)

@ -18,6 +18,7 @@ package client
import (
"encoding/json"
"errors"
"io/ioutil"
"net/http"
"os"
@ -100,11 +101,20 @@ func (c *Client) DeleteDeployment(name string) (*common.Deployment, error) {
return deployment, err
}
// DescribeDeployment describes the kubernetes resources of the supplied deployment
func (c *Client) DescribeDeployment(name string) (*common.Deployment, error) {
var deployment *common.Deployment
//TODO: implement
return deployment, nil
// DescribeDeployment describes the kubernetes resources of the supplied deployment by fetching the
// latest manifest.
func (c *Client) DescribeDeployment(name string) (*common.Manifest, error) {
var manifest *common.Manifest
deployment, err := c.GetDeployment(name)
if err != nil {
return nil, err
}
if deployment.LatestManifest == "" {
return nil, errors.New("Deployment: '" + name + "' has no manifest")
}
_, err = c.Get(fancypath.Join("deployments", name, "manifests", deployment.LatestManifest), &manifest)
return manifest, err
}
// PostDeployment posts a deployment object to the manager service.

@ -19,6 +19,7 @@ package client
import (
"fmt"
"net/http"
"strings"
"testing"
"github.com/kubernetes/helm/pkg/common"
@ -64,6 +65,81 @@ func TestGetDeployment(t *testing.T) {
}
}
func TestDescribeDeployment(t *testing.T) {
fc := &fakeClient{
handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.Contains(r.URL.String(), "manifest") {
w.Write([]byte(`{"deployment":"guestbook.yaml","name":"manifest-1454962670728402229","expandedConfig":{"resources":[{"name":"fe-rc","type":"ReplicationController","state":{"status":"Created"}},{"name":"fe","type":"Service","state":{"status":"Created"}}]}}`))
} else {
w.Write([]byte(`{"name":"guestbook.yaml","id":0,"createdAt":"2016-02-08T12:17:49.251658308-08:00","deployedAt":"2016-02-08T12:17:49.251658589-08:00","modifiedAt":"2016-02-08T12:17:51.177518098-08:00","deletedAt":"0001-01-01T00:00:00Z","state":{"status":"Deployed"},"latestManifest":"manifest-1454962670728402229"}`))
}
}),
}
defer fc.teardown()
m, err := fc.setup().DescribeDeployment("guestbook.yaml")
if err != nil {
t.Fatal(err)
}
if m.Deployment != "guestbook.yaml" {
t.Fatalf("expected deployment name 'guestbook.yaml', got '%s'", m.Name)
}
if m.Name != "manifest-1454962670728402229" {
t.Fatalf("expected manifest name 'manifest-1454962670728402229', got '%s'", m.Name)
}
if len(m.ExpandedConfig.Resources) != 2 {
t.Fatalf("expected two resources, got %d", len(m.ExpandedConfig.Resources))
}
var foundFE = false
var foundFERC = false
for _, r := range m.ExpandedConfig.Resources {
if r.Name == "fe" {
foundFE = true
if r.Type != "Service" {
t.Fatalf("Incorrect type, expected 'Service' got '%s'", r.Type)
}
}
if r.Name == "fe-rc" {
foundFERC = true
if r.Type != "ReplicationController" {
t.Fatalf("Incorrect type, expected 'ReplicationController' got '%s'", r.Type)
}
}
if r.State.Status != common.Created {
t.Fatalf("Incorrect status, expected '%s' got '%s'", common.Created, r.State.Status)
}
}
if !foundFE {
t.Fatalf("didn't find 'fe' in resources")
}
if !foundFERC {
t.Fatalf("didn't find 'fe-rc' in resources")
}
}
func TestDescribeDeploymentFailedDeployment(t *testing.T) {
var expectedError = "Deployment: 'guestbook.yaml' has no manifest"
fc := &fakeClient{
handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"name":"guestbook.yaml","createdAt":"2016-04-02T10:41:06.509049871-07:00","deployedAt":"0001-01-01T00:00:00Z","modifiedAt":"2016-04-02T10:41:06.509203582-07:00","deletedAt":"0001-01-01T00:00:00Z","state":{"status":"Failed","errors":["cannot expand configuration:No repository for url gs://kubernetes-charts-testing/redis-2.tgz\n\u0026{[0xc82014efc0]}\n"]},"latestManifest":""}`))
}),
}
defer fc.teardown()
m, err := fc.setup().DescribeDeployment("guestbook.yaml")
if err == nil {
t.Fatal("Did not get an error for missing manifest")
}
if err.Error() != expectedError {
t.Fatalf("Unexpected error message, wanted:\n%s\ngot:\n%s", expectedError, err.Error())
}
if m != nil {
t.Fatal("Got back manifest but shouldn't have")
}
}
func TestPostDeployment(t *testing.T) {
chartInvocation := &common.Resource{
Name: "foo",

Loading…
Cancel
Save