Commit 7ef9bb6f authored by Taylor Thomas's avatar Taylor Thomas

feat(*): Add --wait flag

Adds `--wait` flag to helm that waits for all pods to reach a ready
state, PVCs to be bound, and services to have IP addresses

Closes #1805
parent 7389b341
......@@ -194,6 +194,9 @@ message UpdateReleaseRequest {
int64 timeout = 7;
// ResetValues will cause Tiller to ignore stored values, resetting to default values.
bool reset_values = 8;
// wait, if true, will wait until all Pods, PVCs, and Services are in a ready state
// before marking the release as successful. It will wait for as long as timeout
bool wait = 9;
}
// UpdateReleaseResponse is the response to an update request.
......@@ -214,6 +217,9 @@ message RollbackReleaseRequest {
bool recreate = 5;
// timeout specifies the max amount of time any kubernetes client command can run.
int64 timeout = 6;
// wait, if true, will wait until all Pods, PVCs, and Services are in a ready state
// before marking the release as successful. It will wait for as long as timeout
bool wait = 7;
}
// RollbackReleaseResponse is the response to an update request.
......@@ -248,6 +254,9 @@ message InstallReleaseRequest {
// timeout specifies the max amount of time any kubernetes client command can run.
int64 timeout = 8;
// wait, if true, will wait until all Pods, PVCs, and Services are in a ready state
// before marking the release as successful. It will wait for as long as timeout
bool wait = 9;
}
// InstallReleaseResponse is the response from a release installation.
......
......@@ -112,6 +112,7 @@ type installCmd struct {
nameTemplate string
version string
timeout int64
wait bool
}
type valueFiles []string
......@@ -169,6 +170,7 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command {
f.StringVar(&inst.keyring, "keyring", defaultKeyring(), "location of public keys used for verification")
f.StringVar(&inst.version, "version", "", "specify the exact chart version to install. If this is not specified, the latest version is installed")
f.Int64Var(&inst.timeout, "timeout", 300, "time in seconds to wait for any individual kubernetes operation (like Jobs for hooks)")
f.BoolVar(&inst.wait, "wait", false, "if set, will wait until all Pods, PVCs, and Services are in a ready state before marking the release as successful. It will wait for as long as --timeout")
return cmd
}
......@@ -205,7 +207,8 @@ func (i *installCmd) run() error {
helm.InstallDryRun(i.dryRun),
helm.InstallReuseName(i.replace),
helm.InstallDisableHooks(i.disableHooks),
helm.InstallTimeout(i.timeout))
helm.InstallTimeout(i.timeout),
helm.InstallWait(i.wait))
if err != nil {
return prettyError(err)
}
......
......@@ -98,6 +98,14 @@ func TestInstall(t *testing.T) {
expected: "foobar",
resp: releaseMock(&releaseOptions{name: "foobar"}),
},
// Install, with wait
{
name: "install with a wait",
args: []string{"testdata/testcharts/alpine"},
flags: strings.Split("--wait", " "),
expected: "apollo",
resp: releaseMock(&releaseOptions{name: "apollo"}),
},
// Install, using the name-template
{
name: "install with name-template",
......
......@@ -43,6 +43,7 @@ type rollbackCmd struct {
out io.Writer
client helm.Interface
timeout int64
wait bool
}
func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command {
......@@ -79,6 +80,7 @@ func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command {
f.BoolVar(&rollback.recreate, "recreate-pods", false, "performs pods restart for the resource if applicable")
f.BoolVar(&rollback.disableHooks, "no-hooks", false, "prevent hooks from running during rollback")
f.Int64Var(&rollback.timeout, "timeout", 300, "time in seconds to wait for any individual kubernetes operation (like Jobs for hooks)")
f.BoolVar(&rollback.wait, "wait", false, "if set, will wait until all Pods, PVCs, and Services are in a ready state before marking the release as successful. It will wait for as long as --timeout")
return cmd
}
......@@ -90,7 +92,8 @@ func (r *rollbackCmd) run() error {
helm.RollbackRecreate(r.recreate),
helm.RollbackDisableHooks(r.disableHooks),
helm.RollbackVersion(r.revision),
helm.RollbackTimeout(r.timeout))
helm.RollbackTimeout(r.timeout),
helm.RollbackWait(r.wait))
if err != nil {
return prettyError(err)
}
......
......@@ -37,6 +37,12 @@ func TestRollbackCmd(t *testing.T) {
flags: []string{"--timeout", "120"},
expected: "Rollback was a success! Happy Helming!",
},
{
name: "rollback a release with wait",
args: []string{"funny-honey", "1"},
flags: []string{"--wait"},
expected: "Rollback was a success! Happy Helming!",
},
{
name: "rollback a release without revision",
args: []string{"funny-honey"},
......
......@@ -71,6 +71,7 @@ type upgradeCmd struct {
version string
timeout int64
resetValues bool
wait bool
}
func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command {
......@@ -112,6 +113,7 @@ func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command {
f.StringVar(&upgrade.version, "version", "", "specify the exact chart version to use. If this is not specified, the latest version is used")
f.Int64Var(&upgrade.timeout, "timeout", 300, "time in seconds to wait for any individual kubernetes operation (like Jobs for hooks)")
f.BoolVar(&upgrade.resetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart")
f.BoolVar(&upgrade.wait, "wait", false, "if set, will wait until all Pods, PVCs, and Services are in a ready state before marking the release as successful. It will wait for as long as --timeout")
f.MarkDeprecated("disable-hooks", "use --no-hooks instead")
......@@ -147,6 +149,7 @@ func (u *upgradeCmd) run() error {
values: u.values,
namespace: u.namespace,
timeout: u.timeout,
wait: u.wait,
}
return ic.run()
}
......@@ -165,7 +168,8 @@ func (u *upgradeCmd) run() error {
helm.UpgradeRecreate(u.recreate),
helm.UpgradeDisableHooks(u.disableHooks),
helm.UpgradeTimeout(u.timeout),
helm.ResetValues(u.resetValues))
helm.ResetValues(u.resetValues),
helm.UpgradeWait(u.wait))
if err != nil {
return fmt.Errorf("UPGRADE FAILED: %v", prettyError(err))
}
......
......@@ -114,6 +114,13 @@ func TestUpgradeCmd(t *testing.T) {
resp: releaseMock(&releaseOptions{name: "crazy-bunny", version: 1, chart: ch}),
expected: "Release \"crazy-bunny\" has been upgraded. Happy Helming!\n",
},
{
name: "upgrade a release with wait",
args: []string{"crazy-bunny", chartPath},
flags: []string{"--wait"},
resp: releaseMock(&releaseOptions{name: "crazy-bunny", version: 2, chart: ch2}),
expected: "Release \"crazy-bunny\" has been upgraded. Happy Helming!\n",
},
}
cmd := func(c *fakeReleaseClient, out io.Writer) *cobra.Command {
......
......@@ -181,6 +181,27 @@ func RollbackTimeout(timeout int64) RollbackOption {
}
}
// InstallWait specifies whether or not to wait for all resources to be ready
func InstallWait(wait bool) InstallOption {
return func(opts *options) {
opts.instReq.Wait = wait
}
}
// UpgradeWait specifies whether or not to wait for all resources to be ready
func UpgradeWait(wait bool) UpdateOption {
return func(opts *options) {
opts.updateReq.Wait = wait
}
}
// RollbackWait specifies whether or not to wait for all resources to be ready
func RollbackWait(wait bool) RollbackOption {
return func(opts *options) {
opts.rollbackReq.Wait = wait
}
}
// UpdateValueOverrides specifies a list of values to include when upgrading
func UpdateValueOverrides(raw []byte) UpdateOption {
return func(opts *options) {
......
......@@ -30,6 +30,7 @@ import (
"k8s.io/kubernetes/pkg/api/v1"
apps "k8s.io/kubernetes/pkg/apis/apps/v1beta1"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
......@@ -40,6 +41,7 @@ import (
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/strategicpatch"
"k8s.io/kubernetes/pkg/util/wait"
"k8s.io/kubernetes/pkg/watch"
)
......@@ -67,7 +69,7 @@ type ResourceActorFunc func(*resource.Info) error
// Create creates kubernetes resources from an io.reader
//
// Namespace will set the namespace
func (c *Client) Create(namespace string, reader io.Reader) error {
func (c *Client) Create(namespace string, reader io.Reader, timeout int64, shouldWait bool) error {
client, err := c.ClientSet()
if err != nil {
return err
......@@ -75,7 +77,18 @@ func (c *Client) Create(namespace string, reader io.Reader) error {
if err := ensureNamespace(client, namespace); err != nil {
return err
}
return perform(c, namespace, reader, createResource)
infos, buildErr := c.Build(namespace, reader)
if buildErr != nil {
return buildErr
}
err = perform(c, namespace, infos, createResource)
if err != nil {
return err
}
if shouldWait {
err = c.waitForResources(time.Duration(timeout)*time.Second, infos)
}
return err
}
func (c *Client) newBuilder(namespace string, reader io.Reader) *resource.Result {
......@@ -107,7 +120,11 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) {
// Since we don't know what order the objects come in, let's group them by the types, so
// that when we print them, they come looking good (headers apply to subgroups, etc.)
objs := make(map[string][]runtime.Object)
err := perform(c, namespace, reader, func(info *resource.Info) error {
infos, err := c.Build(namespace, reader)
if err != nil {
return "", err
}
err = perform(c, namespace, infos, func(info *resource.Info) error {
log.Printf("Doing get for: '%s'", info.Name)
obj, err := resource.NewHelper(info.Client, info.Mapping).Get(info.Namespace, info.Name, info.Export)
if err != nil {
......@@ -159,7 +176,7 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) {
// not present in the target configuration
//
// Namespace will set the namespaces
func (c *Client) Update(namespace string, originalReader, targetReader io.Reader, recreate bool) error {
func (c *Client) Update(namespace string, originalReader, targetReader io.Reader, recreate bool, timeout int64, shouldWait bool) error {
original, err := c.Build(namespace, originalReader)
if err != nil {
return fmt.Errorf("failed decoding reader into objects: %s", err)
......@@ -224,6 +241,12 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader
log.Printf("Failed to delete %s, err: %s", info.Name, err)
}
}
if shouldWait {
err = c.waitForResources(time.Duration(timeout)*time.Second, target)
}
if err != nil {
return err
}
return nil
}
......@@ -231,7 +254,11 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader
//
// Namespace will set the namespace
func (c *Client) Delete(namespace string, reader io.Reader) error {
return perform(c, namespace, reader, func(info *resource.Info) error {
infos, err := c.Build(namespace, reader)
if err != nil {
return err
}
return perform(c, namespace, infos, func(info *resource.Info) error {
log.Printf("Starting delete for %s %s", info.Name, info.Mapping.GroupVersionKind.Kind)
err := deleteResource(c, info)
return skipIfNotFound(err)
......@@ -264,18 +291,18 @@ func watchTimeout(t time.Duration) ResourceActorFunc {
// ascertained by watching the Status fields in a job's output.
//
// Handling for other kinds will be added as necessary.
func (c *Client) WatchUntilReady(namespace string, reader io.Reader, timeout int64) error {
func (c *Client) WatchUntilReady(namespace string, reader io.Reader, timeout int64, shouldWait bool) error {
infos, err := c.Build(namespace, reader)
if err != nil {
return err
}
// For jobs, there's also the option to do poll c.Jobs(namespace).Get():
// https://github.com/adamreese/kubernetes/blob/master/test/e2e/job.go#L291-L300
return perform(c, namespace, reader, watchTimeout(time.Duration(timeout)*time.Second))
return perform(c, namespace, infos, watchTimeout(time.Duration(timeout)*time.Second))
}
func perform(c *Client, namespace string, reader io.Reader, fn ResourceActorFunc) error {
infos, err := c.Build(namespace, reader)
switch {
case err != nil:
return err
case len(infos) == 0:
func perform(c *Client, namespace string, infos Result, fn ResourceActorFunc) error {
if len(infos) == 0 {
return ErrNoObjectsVisited
}
for _, info := range infos {
......@@ -287,8 +314,12 @@ func perform(c *Client, namespace string, reader io.Reader, fn ResourceActorFunc
}
func createResource(info *resource.Info) error {
_, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object)
obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object)
if err != nil {
return err
}
info.Refresh(obj, true)
return nil
}
func deleteResource(c *Client, info *resource.Info) error {
......@@ -328,7 +359,8 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object,
// send patch to server
helper := resource.NewHelper(target.Client, target.Mapping)
if _, err = helper.Patch(target.Namespace, target.Name, api.StrategicMergePatchType, patch); err != nil {
var obj runtime.Object
if obj, err = helper.Patch(target.Namespace, target.Name, api.StrategicMergePatchType, patch); err != nil {
return err
}
......@@ -336,6 +368,7 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object,
client, _ := c.ClientSet()
return recreatePods(client, target.Namespace, extractSelector(currentObj))
}
target.Refresh(obj, true)
return nil
}
......@@ -418,6 +451,132 @@ func watchUntilReady(timeout time.Duration, info *resource.Info) error {
return err
}
func podsReady(pods []api.Pod) bool {
if len(pods) == 0 {
return true
}
for _, pod := range pods {
if !api.IsPodReady(&pod) {
return false
}
}
return true
}
func servicesReady(svc []api.Service) bool {
if len(svc) == 0 {
return true
}
for _, s := range svc {
if !api.IsServiceIPSet(&s) {
return false
}
// This checks if the service has a LoadBalancer and that balancer has an Ingress defined
if s.Spec.Type == api.ServiceTypeLoadBalancer && s.Status.LoadBalancer.Ingress == nil {
return false
}
}
return true
}
func volumesReady(vols []api.PersistentVolumeClaim) bool {
if len(vols) == 0 {
return true
}
for _, v := range vols {
if v.Status.Phase != api.ClaimBound {
return false
}
}
return true
}
func getPods(client *internalclientset.Clientset, namespace string, selector map[string]string) ([]api.Pod, error) {
list, err := client.Pods(namespace).List(api.ListOptions{
FieldSelector: fields.Everything(),
LabelSelector: labels.Set(selector).AsSelector(),
})
if err != nil {
return nil, err
}
return list.Items, nil
}
// waitForResources polls to get the current status of all pods, PVCs, and Services
// until all are ready or a timeout is reached
func (c *Client) waitForResources(timeout time.Duration, created Result) error {
log.Printf("beginning wait for resources with timeout of %v", timeout)
client, _ := c.ClientSet()
return wait.Poll(2*time.Second, timeout, func() (bool, error) {
pods := []api.Pod{}
services := []api.Service{}
pvc := []api.PersistentVolumeClaim{}
for _, v := range created {
switch value := v.Object.(type) {
case (*api.ReplicationController):
list, err := getPods(client, value.Namespace, value.Spec.Selector)
if err != nil {
return false, err
}
pods = append(pods, list...)
case (*api.Pod):
pod, err := client.Pods(value.Namespace).Get(value.Name)
if err != nil {
return false, err
}
pods = append(pods, *pod)
case (*extensions.Deployment):
// Get the RS children first
rs, err := client.ReplicaSets(value.Namespace).List(api.ListOptions{
FieldSelector: fields.Everything(),
LabelSelector: labels.Set(value.Spec.Selector.MatchLabels).AsSelector(),
})
if err != nil {
return false, err
}
for _, r := range rs.Items {
list, err := getPods(client, value.Namespace, r.Spec.Selector.MatchLabels)
if err != nil {
return false, err
}
pods = append(pods, list...)
}
case (*extensions.DaemonSet):
list, err := getPods(client, value.Namespace, value.Spec.Selector.MatchLabels)
if err != nil {
return false, err
}
pods = append(pods, list...)
case (*apps.StatefulSet):
list, err := getPods(client, value.Namespace, value.Spec.Selector.MatchLabels)
if err != nil {
return false, err
}
pods = append(pods, list...)
case (*extensions.ReplicaSet):
list, err := getPods(client, value.Namespace, value.Spec.Selector.MatchLabels)
if err != nil {
return false, err
}
pods = append(pods, list...)
case (*api.PersistentVolumeClaim):
claim, err := client.PersistentVolumeClaims(value.Namespace).Get(value.Name)
if err != nil {
return false, err
}
pvc = append(pvc, *claim)
case (*api.Service):
svc, err := client.Services(value.Namespace).Get(value.Name)
if err != nil {
return false, err
}
services = append(services, *svc)
}
}
return podsReady(pods) && servicesReady(services) && volumesReady(pvc), nil
})
}
// waitForJob is a helper that waits for a job to complete.
//
// This operates on an event returned from a watcher.
......
......@@ -105,7 +105,9 @@ func (f *fakeReaperFactory) Reaper(mapping *meta.RESTMapping) (kubectl.Reaper, e
func TestUpdate(t *testing.T) {
listA := newPodList("starfish", "otter", "squid")
listB := newPodList("starfish", "otter", "dolphin")
listC := newPodList("starfish", "otter", "dolphin")
listB.Items[0].Spec.Containers[0].Ports = []api.ContainerPort{{Name: "https", ContainerPort: 443}}
listC.Items[0].Spec.Containers[0].Ports = []api.ContainerPort{{Name: "https", ContainerPort: 443}}
actions := make(map[string]string)
......@@ -148,10 +150,19 @@ func TestUpdate(t *testing.T) {
reaper := &fakeReaper{}
rf := &fakeReaperFactory{Factory: f, reaper: reaper}
c := &Client{Factory: rf}
if err := c.Update(api.NamespaceDefault, objBody(codec, &listA), objBody(codec, &listB), false); err != nil {
if err := c.Update(api.NamespaceDefault, objBody(codec, &listA), objBody(codec, &listB), false, 0, false); err != nil {
t.Fatal(err)
}
// TODO: Find a way to test methods that use Client Set
// Test with a wait
// if err := c.Update("test", objBody(codec, &listB), objBody(codec, &listC), false, 300, true); err != nil {
// t.Fatal(err)
// }
// Test with a wait should fail
// TODO: A way to make this not based off of an extremely short timeout?
// if err := c.Update("test", objBody(codec, &listC), objBody(codec, &listA), false, 2, true); err != nil {
// t.Fatal(err)
// }
expectedActions := map[string]string{
"/namespaces/default/pods/dolphin": "GET",
"/namespaces/default/pods/otter": "GET",
......@@ -171,7 +182,7 @@ func TestUpdate(t *testing.T) {
}
func TestPerform(t *testing.T) {
func TestBuild(t *testing.T) {
tests := []struct {
name string
namespace string
......@@ -186,12 +197,6 @@ func TestPerform(t *testing.T) {
namespace: "test",
reader: strings.NewReader(guestbookManifest),
count: 6,
}, {
name: "Empty manifests",
namespace: "test",
reader: strings.NewReader(""),
err: true,
errMessage: "no objects visited",
}, {
name: "Invalid schema",
namespace: "test",
......@@ -202,6 +207,59 @@ func TestPerform(t *testing.T) {
},
}
for _, tt := range tests {
f, tf, _, _ := cmdtesting.NewAPIFactory()
c := &Client{Factory: f}
if tt.swaggerFile != "" {
data, err := ioutil.ReadFile(tt.swaggerFile)
if err != nil {
t.Fatalf("could not read swagger spec: %s", err)
}
validator, err := validation.NewSwaggerSchemaFromBytes(data, nil)
if err != nil {
t.Fatalf("could not load swagger spec: %s", err)
}
tf.Validator = validator
}
// Test for an invalid manifest
infos, err := c.Build(tt.namespace, tt.reader)
if err != nil && err.Error() != tt.errMessage {
t.Errorf("%q. expected error message: %v, got %v", tt.name, tt.errMessage, err)
} else if err != nil && !tt.err {
t.Errorf("%q. Got error message when no error should have occurred: %v, got %v", tt.name, tt.errMessage, err)
}
if len(infos) != tt.count {
t.Errorf("%q. expected %d result objects, got %d", tt.name, tt.count, len(infos))
}
}
}
func TestPerform(t *testing.T) {
tests := []struct {
name string
namespace string
reader io.Reader
count int
swaggerFile string
err bool
errMessage string
}{
{
name: "Valid input",
namespace: "test",
reader: strings.NewReader(guestbookManifest),
count: 6,
}, {
name: "Empty manifests",
namespace: "test",
reader: strings.NewReader(""),
err: true,
errMessage: "no objects visited",
},
}
for _, tt := range tests {
results := []*resource.Info{}
......@@ -228,7 +286,12 @@ func TestPerform(t *testing.T) {
tf.Validator = validator
}
err := perform(c, tt.namespace, tt.reader, fn)
infos, err := c.Build(tt.namespace, tt.reader)
if err != nil && err.Error() != tt.errMessage {
t.Errorf("%q. Error while building manifests: %v", tt.name, err)
}
err = perform(c, tt.namespace, infos, fn)
if (err != nil) != tt.err {
t.Errorf("%q. expected error: %v, got %v", tt.name, tt.err, err)
}
......@@ -245,13 +308,13 @@ func TestPerform(t *testing.T) {
func TestReal(t *testing.T) {
t.Skip("This is a live test, comment this line to run")
c := New(nil)
if err := c.Create("test", strings.NewReader(guestbookManifest)); err != nil {
if err := c.Create("test", strings.NewReader(guestbookManifest), 300, false); err != nil {
t.Fatal(err)
}
testSvcEndpointManifest := testServiceManifest + "\n---\n" + testEndpointManifest
c = New(nil)
if err := c.Create("test-delete", strings.NewReader(testSvcEndpointManifest)); err != nil {
if err := c.Create("test-delete", strings.NewReader(testSvcEndpointManifest), 300, false); err != nil {
t.Fatal(err)
}
......
......@@ -252,6 +252,9 @@ type UpdateReleaseRequest struct {
Timeout int64 `protobuf:"varint,7,opt,name=timeout" json:"timeout,omitempty"`
// ResetValues will cause Tiller to ignore stored values, resetting to default values.
ResetValues bool `protobuf:"varint,8,opt,name=reset_values,json=resetValues" json:"reset_values,omitempty"`
// wait, if true, will wait until all Pods, PVCs, and Services are in a ready state
// before marking the release as successful. It will wait for as long as timeout
Wait bool `protobuf:"varint,9,opt,name=wait" json:"wait,omitempty"`
}
func (m *UpdateReleaseRequest) Reset() { *m = UpdateReleaseRequest{} }
......@@ -303,6 +306,9 @@ type RollbackReleaseRequest struct {
Recreate bool `protobuf:"varint,5,opt,name=recreate" json:"recreate,omitempty"`
// timeout specifies the max amount of time any kubernetes client command can run.
Timeout int64 `protobuf:"varint,6,opt,name=timeout" json:"timeout,omitempty"`
// wait, if true, will wait until all Pods, PVCs, and Services are in a ready state
// before marking the release as successful. It will wait for as long as timeout
Wait bool `protobuf:"varint,7,opt,name=wait" json:"wait,omitempty"`
}
func (m *RollbackReleaseRequest) Reset() { *m = RollbackReleaseRequest{} }
......@@ -349,6 +355,9 @@ type InstallReleaseRequest struct {
ReuseName bool `protobuf:"varint,7,opt,name=reuse_name,json=reuseName" json:"reuse_name,omitempty"`
// timeout specifies the max amount of time any kubernetes client command can run.
Timeout int64 `protobuf:"varint,8,opt,name=timeout" json:"timeout,omitempty"`
// wait, if true, will wait until all Pods, PVCs, and Services are in a ready state
// before marking the release as successful. It will wait for as long as timeout
Wait bool `protobuf:"varint,9,opt,name=wait" json:"wait,omitempty"`
}
func (m *InstallReleaseRequest) Reset() { *m = InstallReleaseRequest{} }
......@@ -894,73 +903,74 @@ var _ReleaseService_serviceDesc = grpc.ServiceDesc{
func init() { proto.RegisterFile("hapi/services/tiller.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 1075 bytes of a gzipped FileDescriptorProto
// 1092 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x57, 0xdd, 0x6e, 0xe3, 0x44,
0x14, 0xae, 0xf3, 0xe3, 0x24, 0xa7, 0x3f, 0xa4, 0xb3, 0xfd, 0x71, 0x2d, 0x40, 0xc5, 0x08, 0x36,
0x2c, 0x6c, 0x0a, 0xe1, 0x0a, 0x09, 0x21, 0x75, 0xb3, 0x51, 0x5a, 0x28, 0x59, 0xc9, 0xa1, 0x8b,
0xc4, 0x05, 0x91, 0x9b, 0x4c, 0xb6, 0x66, 0x1d, 0x4f, 0xf0, 0x4c, 0xaa, 0xcd, 0x2d, 0x77, 0x3c,
0x00, 0x3c, 0x00, 0x8f, 0xc1, 0x53, 0xf1, 0x08, 0xc8, 0xf3, 0xe3, 0x66, 0x5c, 0x3b, 0xeb, 0xcd,
0x4d, 0xec, 0x99, 0x73, 0xe6, 0x3b, 0xe7, 0x7c, 0x73, 0x7e, 0x1c, 0xb0, 0x6f, 0xbd, 0xb9, 0x7f,
0x46, 0x71, 0x74, 0xe7, 0x8f, 0x31, 0x3d, 0x63, 0x7e, 0x10, 0xe0, 0xa8, 0x3d, 0x8f, 0x08, 0x23,
0xe8, 0x20, 0x96, 0xb5, 0x95, 0xac, 0x2d, 0x64, 0xf6, 0x11, 0x3f, 0x31, 0xbe, 0xf5, 0x22, 0x26,
0x7e, 0x85, 0xb6, 0x7d, 0xbc, 0xba, 0x4f, 0xc2, 0xa9, 0xff, 0x4a, 0x0a, 0x84, 0x89, 0x08, 0x07,
0xd8, 0xa3, 0x58, 0x3d, 0xb5, 0x43, 0x4a, 0xe6, 0x87, 0x53, 0x22, 0x05, 0x27, 0x9a, 0x80, 0x32,
0x8f, 0x2d, 0xa8, 0x86, 0x77, 0x87, 0x23, 0xea, 0x93, 0x50, 0x3d, 0x85, 0xcc, 0xf9, 0xa7, 0x04,
0x8f, 0xae, 0x7c, 0xca, 0x5c, 0x71, 0x90, 0xba, 0xf8, 0xf7, 0x05, 0xa6, 0x0c, 0x1d, 0x40, 0x35,
0xf0, 0x67, 0x3e, 0xb3, 0x8c, 0x53, 0xa3, 0x55, 0x76, 0xc5, 0x02, 0x1d, 0x81, 0x49, 0xa6, 0x53,
0x8a, 0x99, 0x55, 0x3a, 0x35, 0x5a, 0x0d, 0x57, 0xae, 0xd0, 0x77, 0x50, 0xa3, 0x24, 0x62, 0xa3,
0x9b, 0xa5, 0x55, 0x3e, 0x35, 0x5a, 0x7b, 0x9d, 0x4f, 0xda, 0x59, 0x54, 0xb4, 0x63, 0x4b, 0x43,
0x12, 0xb1, 0x76, 0xfc, 0xf3, 0x6c, 0xe9, 0x9a, 0x94, 0x3f, 0x63, 0xdc, 0xa9, 0x1f, 0x30, 0x1c,
0x59, 0x15, 0x81, 0x2b, 0x56, 0xa8, 0x0f, 0xc0, 0x71, 0x49, 0x34, 0xc1, 0x91, 0x55, 0xe5, 0xd0,
0xad, 0x02, 0xd0, 0x2f, 0x62, 0x7d, 0xb7, 0x41, 0xd5, 0x2b, 0xfa, 0x16, 0x76, 0x04, 0x25, 0xa3,
0x31, 0x99, 0x60, 0x6a, 0x99, 0xa7, 0xe5, 0xd6, 0x5e, 0xe7, 0x44, 0x40, 0x29, 0x86, 0x87, 0x82,
0xb4, 0x2e, 0x99, 0x60, 0x77, 0x5b, 0xa8, 0xc7, 0xef, 0xd4, 0xf9, 0x15, 0xea, 0x0a, 0xde, 0xe9,
0x80, 0x29, 0x9c, 0x47, 0xdb, 0x50, 0xbb, 0x1e, 0xfc, 0x30, 0x78, 0xf1, 0xf3, 0xa0, 0xb9, 0x85,
0xea, 0x50, 0x19, 0x9c, 0xff, 0xd8, 0x6b, 0x1a, 0x68, 0x1f, 0x76, 0xaf, 0xce, 0x87, 0x3f, 0x8d,
0xdc, 0xde, 0x55, 0xef, 0x7c, 0xd8, 0x7b, 0xde, 0x2c, 0x39, 0x1f, 0x42, 0x23, 0xf1, 0x0a, 0xd5,
0xa0, 0x7c, 0x3e, 0xec, 0x8a, 0x23, 0xcf, 0x7b, 0xc3, 0x6e, 0xd3, 0x70, 0xfe, 0x34, 0xe0, 0x40,
0xbf, 0x04, 0x3a, 0x27, 0x21, 0xc5, 0xf1, 0x2d, 0x8c, 0xc9, 0x22, 0x4c, 0x6e, 0x81, 0x2f, 0x10,
0x82, 0x4a, 0x88, 0xdf, 0xa8, 0x3b, 0xe0, 0xef, 0xb1, 0x26, 0x23, 0xcc, 0x0b, 0x38, 0xff, 0x65,
0x57, 0x2c, 0xd0, 0x57, 0x50, 0x97, 0xc1, 0x51, 0xab, 0x72, 0x5a, 0x6e, 0x6d, 0x77, 0x0e, 0xf5,
0x90, 0xa5, 0x45, 0x37, 0x51, 0x73, 0xfa, 0x70, 0xdc, 0xc7, 0xca, 0x13, 0xc1, 0x88, 0xca, 0x89,
0xd8, 0xae, 0x37, 0xc3, 0xdc, 0x99, 0xd8, 0xae, 0x37, 0xc3, 0xc8, 0x82, 0x9a, 0x4c, 0x28, 0xee,
0x4e, 0xd5, 0x55, 0x4b, 0x87, 0x81, 0xf5, 0x10, 0x48, 0xc6, 0x95, 0x85, 0xf4, 0x29, 0x54, 0xe2,
0x74, 0xe6, 0x30, 0xdb, 0x1d, 0xa4, 0xfb, 0x79, 0x19, 0x4e, 0x89, 0xcb, 0xe5, 0xe8, 0x7d, 0x68,
0xc4, 0xfa, 0x74, 0xee, 0x8d, 0x31, 0x8f, 0xb6, 0xe1, 0xde, 0x6f, 0x38, 0x17, 0xab, 0x56, 0xbb,
0x24, 0x64, 0x38, 0x64, 0x9b, 0xf9, 0x7f, 0x05, 0x27, 0x19, 0x48, 0x32, 0x80, 0x33, 0xa8, 0x49,
0xd7, 0x38, 0x5a, 0x2e, 0xaf, 0x4a, 0xcb, 0xf9, 0xbb, 0x04, 0x07, 0xd7, 0xf3, 0x89, 0xc7, 0xb0,
0x12, 0xad, 0x71, 0xea, 0x31, 0x54, 0x79, 0x5b, 0x90, 0x5c, 0xec, 0x0b, 0x6c, 0xd1, 0x3b, 0xba,
0xf1, 0xaf, 0x2b, 0xe4, 0xe8, 0x09, 0x98, 0x77, 0x5e, 0xb0, 0xc0, 0x94, 0x13, 0x91, 0xb0, 0x26,
0x35, 0x79, 0x4f, 0x71, 0xa5, 0x06, 0x3a, 0x86, 0xda, 0x24, 0x5a, 0x8e, 0xa2, 0x45, 0xc8, 0x8b,
0xac, 0xee, 0x9a, 0x93, 0x68, 0xe9, 0x2e, 0x42, 0xf4, 0x31, 0xec, 0x4e, 0x7c, 0xea, 0xdd, 0x04,
0x78, 0x74, 0x4b, 0xc8, 0x6b, 0xca, 0xeb, 0xac, 0xee, 0xee, 0xc8, 0xcd, 0x8b, 0x78, 0x0f, 0xd9,
0x71, 0x26, 0x8d, 0x23, 0xec, 0x31, 0x6c, 0x99, 0x5c, 0x9e, 0xac, 0x63, 0x0e, 0x99, 0x3f, 0xc3,
0x64, 0xc1, 0xac, 0x1a, 0xcf, 0x3e, 0xb5, 0x44, 0x1f, 0xc1, 0x4e, 0x84, 0x29, 0x66, 0x23, 0xe9,
0x65, 0x9d, 0x9f, 0xdc, 0xe6, 0x7b, 0x2f, 0xf9, 0x96, 0x73, 0x01, 0x87, 0x29, 0x5e, 0x36, 0xa5,
0xf8, 0x5f, 0x03, 0x8e, 0x5c, 0x12, 0x04, 0x37, 0xde, 0xf8, 0x75, 0x01, 0x92, 0x57, 0xf8, 0x28,
0xad, 0xe7, 0xa3, 0x9c, 0xc1, 0xc7, 0x4a, 0xde, 0x54, 0xb4, 0xbc, 0xd1, 0x98, 0xaa, 0xe6, 0x33,
0x65, 0x6a, 0x4c, 0x39, 0xdf, 0xc3, 0xf1, 0x03, 0xdf, 0x37, 0x25, 0xe2, 0xaf, 0x12, 0x1c, 0x5e,
0x86, 0x94, 0x79, 0x41, 0x90, 0xe2, 0x21, 0x49, 0x2c, 0xa3, 0x70, 0x62, 0x95, 0xde, 0x25, 0xb1,
0xca, 0x1a, 0x91, 0x8a, 0xf5, 0xca, 0x0a, 0xeb, 0x85, 0x92, 0x4d, 0x2b, 0x71, 0x33, 0x55, 0xe2,
0xe8, 0x03, 0x80, 0x08, 0x2f, 0x28, 0x1e, 0x71, 0xf0, 0x1a, 0x3f, 0xdf, 0xe0, 0x3b, 0x03, 0x59,
0xd1, 0x8a, 0xe3, 0xba, 0xce, 0xf1, 0x25, 0x1c, 0xa5, 0x69, 0xd9, 0x94, 0xe2, 0x3f, 0x0c, 0x38,
0xbe, 0x0e, 0xfd, 0x4c, 0x92, 0xb3, 0x92, 0xed, 0x41, 0xd8, 0xa5, 0x8c, 0xb0, 0x0f, 0xa0, 0x3a,
0x5f, 0x44, 0xaf, 0xb0, 0xa4, 0x51, 0x2c, 0x56, 0xe3, 0xa9, 0xe8, 0xf1, 0x8c, 0xc0, 0x7a, 0xe8,
0xc3, 0x86, 0x11, 0xc5, 0x5e, 0x27, 0xed, 0xb7, 0x21, 0x5a, 0xad, 0xf3, 0x08, 0xf6, 0xfb, 0x98,
0xbd, 0x14, 0x89, 0x2d, 0xc3, 0x73, 0x7a, 0x80, 0x56, 0x37, 0xef, 0xed, 0xc9, 0x2d, 0xdd, 0x9e,
0xfa, 0xda, 0x50, 0xfa, 0x4a, 0xcb, 0xf9, 0x86, 0x63, 0x5f, 0xf8, 0x94, 0x91, 0x68, 0xb9, 0x8e,
0xba, 0x26, 0x94, 0x67, 0xde, 0x1b, 0xd9, 0x9d, 0xe3, 0x57, 0xa7, 0xcf, 0x3d, 0x48, 0x8e, 0x4a,
0x0f, 0x56, 0x67, 0x9d, 0x51, 0x68, 0xd6, 0x75, 0xfe, 0xab, 0xc1, 0x9e, 0x1a, 0x50, 0xe2, 0x73,
0x02, 0xf9, 0xb0, 0xb3, 0x3a, 0x89, 0xd1, 0x67, 0xf9, 0x5f, 0x1b, 0xa9, 0x4f, 0x26, 0xfb, 0x49,
0x11, 0x55, 0xe1, 0xac, 0xb3, 0xf5, 0xa5, 0x81, 0x28, 0x34, 0xd3, 0x03, 0x12, 0x3d, 0xcd, 0xc6,
0xc8, 0x99, 0xc8, 0x76, 0xbb, 0xa8, 0xba, 0x32, 0x8b, 0xee, 0x38, 0xed, 0xfa, 0x54, 0x43, 0x6f,
0x85, 0xd1, 0x07, 0xa9, 0x7d, 0x56, 0x58, 0x3f, 0xb1, 0xfb, 0x1b, 0xec, 0x6a, 0x6d, 0x1e, 0xe5,
0xb0, 0x95, 0x35, 0x23, 0xed, 0xcf, 0x0b, 0xe9, 0x26, 0xb6, 0x66, 0xb0, 0xa7, 0xd7, 0x39, 0xca,
0x01, 0xc8, 0x6c, 0x92, 0xf6, 0x17, 0xc5, 0x94, 0x13, 0x73, 0x14, 0x9a, 0xe9, 0x32, 0xcc, 0xbb,
0xc7, 0x9c, 0x96, 0x91, 0x77, 0x8f, 0x79, 0xd5, 0xed, 0x6c, 0x21, 0x0f, 0xe0, 0xbe, 0x0a, 0xd1,
0xe3, 0xdc, 0x0b, 0xd1, 0x8b, 0xd7, 0x6e, 0xbd, 0x5d, 0x31, 0x31, 0x31, 0x87, 0xf7, 0x52, 0x23,
0x09, 0xe5, 0x50, 0x93, 0x3d, 0x75, 0xed, 0xa7, 0x05, 0xb5, 0x53, 0x41, 0xc9, 0xc2, 0x5e, 0x13,
0x94, 0xde, 0x35, 0xd6, 0x04, 0x95, 0xea, 0x11, 0xce, 0xd6, 0x33, 0xf8, 0xa5, 0xae, 0xf4, 0x6e,
0x4c, 0xfe, 0x17, 0xe8, 0xeb, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0x83, 0x62, 0xce, 0x77, 0xd3,
0x0d, 0x00, 0x00,
0x14, 0xae, 0xf3, 0xe3, 0x24, 0xa7, 0x3f, 0xa4, 0xb3, 0x6d, 0xe3, 0x5a, 0x80, 0x82, 0x11, 0x6c,
0x58, 0xd8, 0x14, 0xc2, 0x15, 0x12, 0x42, 0xea, 0x66, 0xa3, 0xb4, 0x50, 0xb2, 0x92, 0x43, 0x17,
0x89, 0x0b, 0x22, 0x37, 0x99, 0x6c, 0xcd, 0x3a, 0x9e, 0xe0, 0x99, 0x94, 0xcd, 0x2d, 0x77, 0xbc,
0x06, 0x77, 0xf0, 0x30, 0x3c, 0x0b, 0x8f, 0x80, 0x3c, 0x3f, 0xae, 0xed, 0xda, 0x59, 0x93, 0x9b,
0xd8, 0x33, 0xe7, 0xcc, 0x77, 0xce, 0xf9, 0xe6, 0xfc, 0x38, 0x60, 0xde, 0x3a, 0x4b, 0xf7, 0x8c,
0xe2, 0xe0, 0xce, 0x9d, 0x62, 0x7a, 0xc6, 0x5c, 0xcf, 0xc3, 0x41, 0x77, 0x19, 0x10, 0x46, 0xd0,
0x51, 0x28, 0xeb, 0x2a, 0x59, 0x57, 0xc8, 0xcc, 0x13, 0x7e, 0x62, 0x7a, 0xeb, 0x04, 0x4c, 0xfc,
0x0a, 0x6d, 0xb3, 0x15, 0xdf, 0x27, 0xfe, 0xdc, 0x7d, 0x25, 0x05, 0xc2, 0x44, 0x80, 0x3d, 0xec,
0x50, 0xac, 0x9e, 0x89, 0x43, 0x4a, 0xe6, 0xfa, 0x73, 0x22, 0x05, 0xa7, 0x09, 0x01, 0x65, 0x0e,
0x5b, 0xd1, 0x04, 0xde, 0x1d, 0x0e, 0xa8, 0x4b, 0x7c, 0xf5, 0x14, 0x32, 0xeb, 0xcf, 0x12, 0x3c,
0xba, 0x72, 0x29, 0xb3, 0xc5, 0x41, 0x6a, 0xe3, 0x5f, 0x57, 0x98, 0x32, 0x74, 0x04, 0x55, 0xcf,
0x5d, 0xb8, 0xcc, 0xd0, 0xda, 0x5a, 0xa7, 0x6c, 0x8b, 0x05, 0x3a, 0x01, 0x9d, 0xcc, 0xe7, 0x14,
0x33, 0xa3, 0xd4, 0xd6, 0x3a, 0x0d, 0x5b, 0xae, 0xd0, 0x37, 0x50, 0xa3, 0x24, 0x60, 0x93, 0x9b,
0xb5, 0x51, 0x6e, 0x6b, 0x9d, 0x83, 0xde, 0x47, 0xdd, 0x2c, 0x2a, 0xba, 0xa1, 0xa5, 0x31, 0x09,
0x58, 0x37, 0xfc, 0x79, 0xb6, 0xb6, 0x75, 0xca, 0x9f, 0x21, 0xee, 0xdc, 0xf5, 0x18, 0x0e, 0x8c,
0x8a, 0xc0, 0x15, 0x2b, 0x34, 0x04, 0xe0, 0xb8, 0x24, 0x98, 0xe1, 0xc0, 0xa8, 0x72, 0xe8, 0x4e,
0x01, 0xe8, 0x17, 0xa1, 0xbe, 0xdd, 0xa0, 0xea, 0x15, 0x7d, 0x0d, 0x7b, 0x82, 0x92, 0xc9, 0x94,
0xcc, 0x30, 0x35, 0xf4, 0x76, 0xb9, 0x73, 0xd0, 0x3b, 0x15, 0x50, 0x8a, 0xe1, 0xb1, 0x20, 0xad,
0x4f, 0x66, 0xd8, 0xde, 0x15, 0xea, 0xe1, 0x3b, 0xb5, 0x7e, 0x86, 0xba, 0x82, 0xb7, 0x7a, 0xa0,
0x0b, 0xe7, 0xd1, 0x2e, 0xd4, 0xae, 0x47, 0xdf, 0x8d, 0x5e, 0xfc, 0x38, 0x6a, 0xee, 0xa0, 0x3a,
0x54, 0x46, 0xe7, 0xdf, 0x0f, 0x9a, 0x1a, 0x3a, 0x84, 0xfd, 0xab, 0xf3, 0xf1, 0x0f, 0x13, 0x7b,
0x70, 0x35, 0x38, 0x1f, 0x0f, 0x9e, 0x37, 0x4b, 0xd6, 0xfb, 0xd0, 0x88, 0xbc, 0x42, 0x35, 0x28,
0x9f, 0x8f, 0xfb, 0xe2, 0xc8, 0xf3, 0xc1, 0xb8, 0xdf, 0xd4, 0xac, 0x3f, 0x34, 0x38, 0x4a, 0x5e,
0x02, 0x5d, 0x12, 0x9f, 0xe2, 0xf0, 0x16, 0xa6, 0x64, 0xe5, 0x47, 0xb7, 0xc0, 0x17, 0x08, 0x41,
0xc5, 0xc7, 0x6f, 0xd4, 0x1d, 0xf0, 0xf7, 0x50, 0x93, 0x11, 0xe6, 0x78, 0x9c, 0xff, 0xb2, 0x2d,
0x16, 0xe8, 0x0b, 0xa8, 0xcb, 0xe0, 0xa8, 0x51, 0x69, 0x97, 0x3b, 0xbb, 0xbd, 0xe3, 0x64, 0xc8,
0xd2, 0xa2, 0x1d, 0xa9, 0x59, 0x43, 0x68, 0x0d, 0xb1, 0xf2, 0x44, 0x30, 0xa2, 0x72, 0x22, 0xb4,
0xeb, 0x2c, 0x30, 0x77, 0x26, 0xb4, 0xeb, 0x2c, 0x30, 0x32, 0xa0, 0x26, 0x13, 0x8a, 0xbb, 0x53,
0xb5, 0xd5, 0xd2, 0x62, 0x60, 0x3c, 0x04, 0x92, 0x71, 0x65, 0x21, 0x7d, 0x0c, 0x95, 0x30, 0x9d,
0x39, 0xcc, 0x6e, 0x0f, 0x25, 0xfd, 0xbc, 0xf4, 0xe7, 0xc4, 0xe6, 0x72, 0xf4, 0x2e, 0x34, 0x42,
0x7d, 0xba, 0x74, 0xa6, 0x98, 0x47, 0xdb, 0xb0, 0xef, 0x37, 0xac, 0x8b, 0xb8, 0xd5, 0x3e, 0xf1,
0x19, 0xf6, 0xd9, 0x76, 0xfe, 0x5f, 0xc1, 0x69, 0x06, 0x92, 0x0c, 0xe0, 0x0c, 0x6a, 0xd2, 0x35,
0x8e, 0x96, 0xcb, 0xab, 0xd2, 0xb2, 0xfe, 0x2e, 0xc1, 0xd1, 0xf5, 0x72, 0xe6, 0x30, 0xac, 0x44,
0x1b, 0x9c, 0x7a, 0x0c, 0x55, 0xde, 0x16, 0x24, 0x17, 0x87, 0x02, 0x5b, 0xf4, 0x8e, 0x7e, 0xf8,
0x6b, 0x0b, 0x39, 0x7a, 0x02, 0xfa, 0x9d, 0xe3, 0xad, 0x30, 0xe5, 0x44, 0x44, 0xac, 0x49, 0x4d,
0xde, 0x53, 0x6c, 0xa9, 0x81, 0x5a, 0x50, 0x9b, 0x05, 0xeb, 0x49, 0xb0, 0xf2, 0x79, 0x91, 0xd5,
0x6d, 0x7d, 0x16, 0xac, 0xed, 0x95, 0x8f, 0x3e, 0x84, 0xfd, 0x99, 0x4b, 0x9d, 0x1b, 0x0f, 0x4f,
0x6e, 0x09, 0x79, 0x4d, 0x79, 0x9d, 0xd5, 0xed, 0x3d, 0xb9, 0x79, 0x11, 0xee, 0x21, 0x33, 0xcc,
0xa4, 0x69, 0x80, 0x1d, 0x86, 0x0d, 0x9d, 0xcb, 0xa3, 0x75, 0xc8, 0x21, 0x73, 0x17, 0x98, 0xac,
0x98, 0x51, 0xe3, 0xd9, 0xa7, 0x96, 0xe8, 0x03, 0xd8, 0x0b, 0x30, 0xc5, 0x6c, 0x22, 0xbd, 0xac,
0xf3, 0x93, 0xbb, 0x7c, 0xef, 0xa5, 0x70, 0x0b, 0x41, 0xe5, 0x37, 0xc7, 0x65, 0x46, 0x83, 0x8b,
0xf8, 0xbb, 0x75, 0x01, 0xc7, 0x29, 0xae, 0xb6, 0xa5, 0xfd, 0x1f, 0x0d, 0x4e, 0x6c, 0xe2, 0x79,
0x37, 0xce, 0xf4, 0x75, 0x01, 0xe2, 0x63, 0x1c, 0x95, 0x36, 0x73, 0x54, 0xce, 0xe0, 0x28, 0x96,
0x4b, 0x95, 0x44, 0x2e, 0x25, 0xd8, 0xab, 0xe6, 0xb3, 0xa7, 0x27, 0xd9, 0x53, 0xd4, 0xd4, 0x62,
0xd4, 0x7c, 0x0b, 0xad, 0x07, 0xf1, 0x6c, 0x4b, 0xce, 0x5f, 0x25, 0x38, 0xbe, 0xf4, 0x29, 0x73,
0x3c, 0x2f, 0xc5, 0x4d, 0x94, 0x80, 0x5a, 0xe1, 0x04, 0x2c, 0xfd, 0x9f, 0x04, 0x2c, 0x27, 0xc8,
0x55, 0x37, 0x51, 0x89, 0xdd, 0x44, 0xa1, 0xa4, 0x4c, 0xb4, 0x02, 0x3d, 0xd5, 0x0a, 0xd0, 0x7b,
0x00, 0x01, 0x5e, 0x51, 0x3c, 0xe1, 0xe0, 0x82, 0xc4, 0x06, 0xdf, 0x19, 0xc9, 0xca, 0x57, 0xbc,
0xd7, 0xb3, 0x79, 0x8f, 0xa7, 0xe4, 0x25, 0x9c, 0xa4, 0xa9, 0xda, 0x96, 0xf6, 0xdf, 0x35, 0x68,
0x5d, 0xfb, 0x6e, 0x26, 0xf1, 0x59, 0x49, 0xf9, 0x80, 0x8a, 0x52, 0x06, 0x15, 0x47, 0x50, 0x5d,
0xae, 0x82, 0x57, 0x58, 0x52, 0x2b, 0x16, 0xf1, 0x18, 0x2b, 0x89, 0x18, 0xad, 0x09, 0x18, 0x0f,
0x7d, 0xd8, 0x32, 0xa2, 0xd0, 0xeb, 0xa8, 0x75, 0x37, 0x44, 0x9b, 0xb6, 0x1e, 0xc1, 0xe1, 0x10,
0xb3, 0x97, 0xa2, 0x00, 0x64, 0x78, 0xd6, 0x00, 0x50, 0x7c, 0xf3, 0xde, 0x9e, 0xdc, 0x4a, 0xda,
0x53, 0x5f, 0x2a, 0x4a, 0x5f, 0x69, 0x59, 0x5f, 0x71, 0xec, 0x0b, 0x97, 0x32, 0x12, 0xac, 0x37,
0x51, 0xd7, 0x84, 0xf2, 0xc2, 0x79, 0x23, 0x3b, 0x7b, 0xf8, 0x6a, 0x0d, 0xb9, 0x07, 0xd1, 0x51,
0xe9, 0x41, 0x7c, 0x4e, 0x6a, 0x85, 0xe6, 0x64, 0xef, 0xdf, 0x1a, 0x1c, 0xa8, 0xe1, 0x26, 0x3e,
0x45, 0x90, 0x0b, 0x7b, 0xf1, 0x29, 0x8e, 0x3e, 0xc9, 0xff, 0x52, 0x49, 0x7d, 0x6e, 0x99, 0x4f,
0x8a, 0xa8, 0x0a, 0x67, 0xad, 0x9d, 0xcf, 0x35, 0x44, 0xa1, 0x99, 0x1e, 0xae, 0xe8, 0x69, 0x36,
0x46, 0xce, 0x34, 0x37, 0xbb, 0x45, 0xd5, 0x95, 0x59, 0x74, 0xc7, 0x69, 0x4f, 0x4e, 0x44, 0xf4,
0x56, 0x98, 0xe4, 0x10, 0x36, 0xcf, 0x0a, 0xeb, 0x47, 0x76, 0x7f, 0x81, 0xfd, 0xc4, 0x38, 0x40,
0x39, 0x6c, 0x65, 0xcd, 0x57, 0xf3, 0xd3, 0x42, 0xba, 0x91, 0xad, 0x05, 0x1c, 0x24, 0xeb, 0x1c,
0xe5, 0x00, 0x64, 0x36, 0x4e, 0xf3, 0xb3, 0x62, 0xca, 0x91, 0x39, 0x0a, 0xcd, 0x74, 0x19, 0xe6,
0xdd, 0x63, 0x4e, 0xcb, 0xc8, 0xbb, 0xc7, 0xbc, 0xea, 0xb6, 0x76, 0x90, 0x03, 0x70, 0x5f, 0x85,
0xe8, 0x71, 0xee, 0x85, 0x24, 0x8b, 0xd7, 0xec, 0xbc, 0x5d, 0x31, 0x32, 0xb1, 0x84, 0x77, 0x52,
0x63, 0x0a, 0xe5, 0x50, 0x93, 0x3d, 0x9d, 0xcd, 0xa7, 0x05, 0xb5, 0x53, 0x41, 0xc9, 0xc2, 0xde,
0x10, 0x54, 0xb2, 0x6b, 0x6c, 0x08, 0x2a, 0xd5, 0x23, 0xac, 0x9d, 0x67, 0xf0, 0x53, 0x5d, 0xe9,
0xdd, 0xe8, 0xfc, 0xef, 0xd3, 0x97, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xbd, 0x3d, 0xae, 0x84,
0x0f, 0x0e, 0x00, 0x00,
}
......@@ -99,7 +99,7 @@ type KubeClient interface {
//
// reader must contain a YAML stream (one or more YAML documents separated
// by "\n---\n").
Create(namespace string, reader io.Reader) error
Create(namespace string, reader io.Reader, timeout int64, shouldWait bool) error
// Get gets one or more resources. Returned string hsa the format like kubectl
// provides with the column headers separating the resource types.
......@@ -123,7 +123,7 @@ type KubeClient interface {
// For Jobs, "ready" means the job ran to completion (excited without error).
// For all other kinds, it means the kind was created or modified without
// error.
WatchUntilReady(namespace string, reader io.Reader, timeout int64) error
WatchUntilReady(namespace string, reader io.Reader, timeout int64, shouldWait bool) error
// Update updates one or more resources or creates the resource
// if it doesn't exist
......@@ -132,7 +132,7 @@ type KubeClient interface {
//
// reader must contain a YAML stream (one or more YAML documents separated
// by "\n---\n").
Update(namespace string, originalReader, modifiedReader io.Reader, recreate bool) error
Update(namespace string, originalReader, modifiedReader io.Reader, recreate bool, timeout int64, shouldWait bool) error
Build(namespace string, reader io.Reader) (kube.Result, error)
}
......@@ -144,7 +144,7 @@ type PrintingKubeClient struct {
}
// Create prints the values of what would be created with a real KubeClient.
func (p *PrintingKubeClient) Create(ns string, r io.Reader) error {
func (p *PrintingKubeClient) Create(ns string, r io.Reader, timeout int64, shouldWait bool) error {
_, err := io.Copy(p.Out, r)
return err
}
......@@ -164,13 +164,13 @@ func (p *PrintingKubeClient) Delete(ns string, r io.Reader) error {
}
// WatchUntilReady implements KubeClient WatchUntilReady.
func (p *PrintingKubeClient) WatchUntilReady(ns string, r io.Reader, t int64) error {
func (p *PrintingKubeClient) WatchUntilReady(ns string, r io.Reader, timeout int64, shouldWait bool) error {
_, err := io.Copy(p.Out, r)
return err
}
// Update implements KubeClient Update.
func (p *PrintingKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, recreate bool) error {
func (p *PrintingKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, recreate bool, timeout int64, shouldWait bool) error {
_, err := io.Copy(p.Out, modifiedReader)
return err
}
......
......@@ -37,7 +37,7 @@ func (e *mockEngine) Render(chrt *chart.Chart, v chartutil.Values) (map[string]s
type mockKubeClient struct{}
func (k *mockKubeClient) Create(ns string, r io.Reader) error {
func (k *mockKubeClient) Create(ns string, r io.Reader, timeout int64, shouldWait bool) error {
return nil
}
func (k *mockKubeClient) Get(ns string, r io.Reader) (string, error) {
......@@ -46,10 +46,10 @@ func (k *mockKubeClient) Get(ns string, r io.Reader) (string, error) {
func (k *mockKubeClient) Delete(ns string, r io.Reader) error {
return nil
}
func (k *mockKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, recreate bool) error {
func (k *mockKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, recreate bool, timeout int64, shouldWait bool) error {
return nil
}
func (k *mockKubeClient) WatchUntilReady(ns string, r io.Reader, t int64) error {
func (k *mockKubeClient) WatchUntilReady(ns string, r io.Reader, timeout int64, shouldWait bool) error {
return nil
}
func (k *mockKubeClient) Build(ns string, reader io.Reader) (kube.Result, error) {
......@@ -91,7 +91,7 @@ func TestKubeClient(t *testing.T) {
b.WriteString(content)
}
if err := env.KubeClient.Create("sharry-bobbins", b); err != nil {
if err := env.KubeClient.Create("sharry-bobbins", b, 300, false); err != nil {
t.Errorf("Kubeclient failed: %s", err)
}
}
......@@ -299,7 +299,7 @@ func (s *ReleaseServer) performUpdate(originalRelease, updatedRelease *release.R
}
}
if err := s.performKubeUpdate(originalRelease, updatedRelease, req.Recreate); err != nil {
if err := s.performKubeUpdate(originalRelease, updatedRelease, req.Recreate, req.Timeout, req.Wait); err != nil {
log.Printf("warning: Release Upgrade %q failed: %s", updatedRelease.Name, err)
originalRelease.Info.Status.Code = release.Status_SUPERSEDED
updatedRelease.Info.Status.Code = release.Status_FAILED
......@@ -453,7 +453,7 @@ func (s *ReleaseServer) performRollback(currentRelease, targetRelease *release.R
}
}
if err := s.performKubeUpdate(currentRelease, targetRelease, req.Recreate); err != nil {
if err := s.performKubeUpdate(currentRelease, targetRelease, req.Recreate, req.Timeout, req.Wait); err != nil {
log.Printf("warning: Release Rollback %q failed: %s", targetRelease.Name, err)
currentRelease.Info.Status.Code = release.Status_SUPERSEDED
targetRelease.Info.Status.Code = release.Status_FAILED
......@@ -477,11 +477,11 @@ func (s *ReleaseServer) performRollback(currentRelease, targetRelease *release.R
return res, nil
}
func (s *ReleaseServer) performKubeUpdate(currentRelease, targetRelease *release.Release, recreate bool) error {
func (s *ReleaseServer) performKubeUpdate(currentRelease, targetRelease *release.Release, recreate bool, timeout int64, shouldWait bool) error {
kubeCli := s.env.KubeClient
current := bytes.NewBufferString(currentRelease.Manifest)
target := bytes.NewBufferString(targetRelease.Manifest)
return kubeCli.Update(targetRelease.Namespace, current, target, recreate)
return kubeCli.Update(targetRelease.Namespace, current, target, recreate, timeout, shouldWait)
}
// prepareRollback finds the previous release and prepares a new release object with
......@@ -820,7 +820,7 @@ func (s *ReleaseServer) performRelease(r *release.Release, req *services.Install
// so as to append to the old release's history
r.Version = old.Version + 1
if err := s.performKubeUpdate(old, r, false); err != nil {
if err := s.performKubeUpdate(old, r, false, req.Timeout, req.Wait); err != nil {
log.Printf("warning: Release replace %q failed: %s", r.Name, err)
old.Info.Status.Code = release.Status_SUPERSEDED
r.Info.Status.Code = release.Status_FAILED
......@@ -833,7 +833,7 @@ func (s *ReleaseServer) performRelease(r *release.Release, req *services.Install
// nothing to replace, create as normal
// regular manifests
b := bytes.NewBufferString(r.Manifest)
if err := s.env.KubeClient.Create(r.Namespace, b); err != nil {
if err := s.env.KubeClient.Create(r.Namespace, b, req.Timeout, req.Wait); err != nil {
log.Printf("warning: Release %q failed: %s", r.Name, err)
r.Info.Status.Code = release.Status_FAILED
s.recordRelease(r, false)
......@@ -885,14 +885,14 @@ func (s *ReleaseServer) execHook(hs []*release.Hook, name, namespace, hook strin
}
b := bytes.NewBufferString(h.Manifest)
if err := kubeCli.Create(namespace, b); err != nil {
if err := kubeCli.Create(namespace, b, timeout, false); err != nil {
log.Printf("warning: Release %q %s %s failed: %s", name, hook, h.Path, err)
return err
}
// No way to rewind a bytes.Buffer()?
b.Reset()
b.WriteString(h.Manifest)
if err := kubeCli.WatchUntilReady(namespace, b, timeout); err != nil {
if err := kubeCli.WatchUntilReady(namespace, b, timeout, false); err != nil {
log.Printf("warning: Release %q %s %s could not complete: %s", name, hook, h.Path, err)
return err
}
......
......@@ -1390,7 +1390,7 @@ type updateFailingKubeClient struct {
environment.PrintingKubeClient
}
func (u *updateFailingKubeClient) Update(namespace string, originalReader, modifiedReader io.Reader, recreate bool) error {
func (u *updateFailingKubeClient) Update(namespace string, originalReader, modifiedReader io.Reader, recreate bool, timeout int64, shouldWait bool) error {
return errors.New("Failed update in kube client")
}
......@@ -1404,7 +1404,7 @@ type hookFailingKubeClient struct {
environment.PrintingKubeClient
}
func (h *hookFailingKubeClient) WatchUntilReady(ns string, r io.Reader, t int64) error {
func (h *hookFailingKubeClient) WatchUntilReady(ns string, r io.Reader, timeout int64, shouldWait bool) error {
return errors.New("Failed watch")
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment