From 5ffe4ce5881449d31b9e14cb94d56dcf2453b0d7 Mon Sep 17 00:00:00 2001 From: Timofey Kirillov Date: Fri, 22 Mar 2019 21:15:00 +0300 Subject: [PATCH 1/4] Fix `no RESOURCE with the name NAME found` This is the fix for only one particular, but important case. The case when a new resource has been added to the chart and there is an error in the chart, which leads to release failure. In this case after first failed release upgrade new resource will be created in the cluster. On the next release upgrade there will be the error: `no RESOURCE with the name NAME found` for this newly created resource from the previous release upgrade. The root of this problem is in the side effect of the first release process, Release invariant says: if resouce exists in the kubernetes cluster, then it should exist in the release storage. But this invariant has been broken by helm itself -- because helm created new resources as side effect and not adopted them into release storage. To maintain release invariant for such case during release upgrade operation all newly *successfully* created resources will be deleted in the case of an error in the subsequent resources update. This behaviour will be enabled only when `--cleanup-on-fail` option used for `helm upgrade` or `helm rollback`. Signed-off-by: Timofey Kirillov --- _proto/hapi/rudder/rudder.proto | 2 + _proto/hapi/services/tiller.proto | 10 ++-- cmd/helm/rollback.go | 27 +++++----- cmd/helm/upgrade.go | 61 ++++++++++++---------- cmd/rudder/rudder.go | 16 +++++- docs/helm/helm_rollback.md | 3 +- docs/helm/helm_upgrade.md | 3 +- pkg/helm/option.go | 14 +++++ pkg/kube/client.go | 52 +++++++++++++++--- pkg/tiller/environment/environment.go | 17 +++++- pkg/tiller/environment/environment_test.go | 3 ++ pkg/tiller/release_modules.go | 16 +++++- pkg/tiller/release_server_test.go | 12 +++++ 13 files changed, 177 insertions(+), 59 deletions(-) diff --git a/_proto/hapi/rudder/rudder.proto b/_proto/hapi/rudder/rudder.proto index 188491512..3f3d8030d 100644 --- a/_proto/hapi/rudder/rudder.proto +++ b/_proto/hapi/rudder/rudder.proto @@ -92,6 +92,7 @@ message UpgradeReleaseRequest{ bool Wait = 4; bool Recreate = 5; bool Force = 6; + bool CleanupOnFail = 7; } message UpgradeReleaseResponse{ hapi.release.Release release = 1; @@ -105,6 +106,7 @@ message RollbackReleaseRequest{ bool Wait = 4; bool Recreate = 5; bool Force = 6; + bool CleanupOnFail = 7; } message RollbackReleaseResponse{ hapi.release.Release release = 1; diff --git a/_proto/hapi/services/tiller.proto b/_proto/hapi/services/tiller.proto index 286d22e8b..1d0cc7ec6 100644 --- a/_proto/hapi/services/tiller.proto +++ b/_proto/hapi/services/tiller.proto @@ -212,8 +212,10 @@ message UpdateReleaseRequest { bool force = 11; // Description, if set, will set the description for the updated release string description = 12; - // Render subchart notes if enabled + // Render subchart notes if enabled bool subNotes = 13; + // Allow deletion of new resources created in this update when update failed + bool cleanup_on_fail = 14; } // UpdateReleaseResponse is the response to an update request. @@ -241,6 +243,8 @@ message RollbackReleaseRequest { bool force = 8; // Description, if set, will set the description for the rollback string description = 9; + // Allow deletion of new resources created in this rollback when rollback failed + bool cleanup_on_fail = 10; } // RollbackReleaseResponse is the response to an update request. @@ -283,8 +287,8 @@ message InstallReleaseRequest { // Description, if set, will set the description for the installed release string description = 11; - - bool subNotes = 12; + + bool subNotes = 12; } diff --git a/cmd/helm/rollback.go b/cmd/helm/rollback.go index 78d79659d..4cffd43d5 100644 --- a/cmd/helm/rollback.go +++ b/cmd/helm/rollback.go @@ -36,17 +36,18 @@ second is a revision (version) number. To see revision numbers, run ` type rollbackCmd struct { - name string - revision int32 - dryRun bool - recreate bool - force bool - disableHooks bool - out io.Writer - client helm.Interface - timeout int64 - wait bool - description string + name string + revision int32 + dryRun bool + recreate bool + force bool + disableHooks bool + out io.Writer + client helm.Interface + timeout int64 + wait bool + description string + cleanupOnFail bool } func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command { @@ -87,6 +88,7 @@ func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command { 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, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout") f.StringVar(&rollback.description, "description", "", "specify a description for the release") + f.BoolVar(&rollback.cleanupOnFail, "cleanup-on-fail", false, "allow deletion of new resources created in this rollback when rollback failed") // set defaults from environment settings.InitTLS(f) @@ -104,7 +106,8 @@ func (r *rollbackCmd) run() error { helm.RollbackVersion(r.revision), helm.RollbackTimeout(r.timeout), helm.RollbackWait(r.wait), - helm.RollbackDescription(r.description)) + helm.RollbackDescription(r.description), + helm.RollbackCleanupOnFail(r.cleanupOnFail)) if err != nil { return prettyError(err) } diff --git a/cmd/helm/upgrade.go b/cmd/helm/upgrade.go index 044ec045d..e52ca2ba3 100644 --- a/cmd/helm/upgrade.go +++ b/cmd/helm/upgrade.go @@ -84,34 +84,35 @@ which results in "pwd: 3jk$o2z=f\30with'quote". ` type upgradeCmd struct { - release string - chart string - out io.Writer - client helm.Interface - dryRun bool - recreate bool - force bool - disableHooks bool - valueFiles valueFiles - values []string - stringValues []string - fileValues []string - verify bool - keyring string - install bool - namespace string - version string - timeout int64 - resetValues bool - reuseValues bool - wait bool - atomic bool - repoURL string - username string - password string - devel bool - subNotes bool - description string + release string + chart string + out io.Writer + client helm.Interface + dryRun bool + recreate bool + force bool + disableHooks bool + valueFiles valueFiles + values []string + stringValues []string + fileValues []string + verify bool + keyring string + install bool + namespace string + version string + timeout int64 + resetValues bool + reuseValues bool + wait bool + atomic bool + repoURL string + username string + password string + devel bool + subNotes bool + description string + cleanupOnFail bool certFile string keyFile string @@ -179,6 +180,7 @@ func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command { f.BoolVar(&upgrade.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.") f.BoolVar(&upgrade.subNotes, "render-subchart-notes", false, "render subchart notes along with parent") f.StringVar(&upgrade.description, "description", "", "specify the description to use for the upgrade, rather than the default") + f.BoolVar(&upgrade.cleanupOnFail, "cleanup-on-fail", false, "allow deletion of new resources created in this upgrade when upgrade failed") f.MarkDeprecated("disable-hooks", "use --no-hooks instead") @@ -273,7 +275,8 @@ func (u *upgradeCmd) run() error { helm.ReuseValues(u.reuseValues), helm.UpgradeSubNotes(u.subNotes), helm.UpgradeWait(u.wait), - helm.UpgradeDescription(u.description)) + helm.UpgradeDescription(u.description), + helm.UpgradeCleanupOnFail(u.cleanupOnFail)) if err != nil { fmt.Fprintf(u.out, "UPGRADE FAILED\nROLLING BACK\nError: %v\n", prettyError(err)) if u.atomic { diff --git a/cmd/rudder/rudder.go b/cmd/rudder/rudder.go index 051640542..d68daf453 100644 --- a/cmd/rudder/rudder.go +++ b/cmd/rudder/rudder.go @@ -131,7 +131,13 @@ func (r *ReleaseModuleServiceServer) RollbackRelease(ctx context.Context, in *ru grpclog.Print("rollback") c := bytes.NewBufferString(in.Current.Manifest) t := bytes.NewBufferString(in.Target.Manifest) - err := kubeClient.Update(in.Target.Namespace, c, t, in.Force, in.Recreate, in.Timeout, in.Wait) + err := kubeClient.UpdateWithOptions(in.Target.Namespace, c, t, kube.UpdateOptions{ + Force: in.Force, + Recreate: in.Recreate, + Timeout: in.Timeout, + ShouldWait: in.Wait, + CleanupOnFail: in.CleanupOnFail, + }) return &rudderAPI.RollbackReleaseResponse{}, err } @@ -140,7 +146,13 @@ func (r *ReleaseModuleServiceServer) UpgradeRelease(ctx context.Context, in *rud grpclog.Print("upgrade") c := bytes.NewBufferString(in.Current.Manifest) t := bytes.NewBufferString(in.Target.Manifest) - err := kubeClient.Update(in.Target.Namespace, c, t, in.Force, in.Recreate, in.Timeout, in.Wait) + err := kubeClient.UpdateWithOptions(in.Target.Namespace, c, t, kube.UpdateOptions{ + Force: in.Force, + Recreate: in.Recreate, + Timeout: in.Timeout, + ShouldWait: in.Wait, + CleanupOnFail: in.CleanupOnFail, + }) // upgrade response object should be changed to include status return &rudderAPI.UpgradeReleaseResponse{}, err } diff --git a/docs/helm/helm_rollback.md b/docs/helm/helm_rollback.md index 80fc83a83..87c68f6c8 100644 --- a/docs/helm/helm_rollback.md +++ b/docs/helm/helm_rollback.md @@ -20,6 +20,7 @@ helm rollback [flags] [RELEASE] [REVISION] ### Options ``` + --cleanup-on-fail allow deletion of new resources created in this rollback when rollback failed --description string specify a description for the release --dry-run simulate a rollback --force force resource update through delete/recreate if needed @@ -52,4 +53,4 @@ helm rollback [flags] [RELEASE] [REVISION] * [helm](helm.md) - The Helm package manager for Kubernetes. -###### Auto generated by spf13/cobra on 29-Jan-2019 +###### Auto generated by spf13/cobra on 5-Feb-2019 diff --git a/docs/helm/helm_upgrade.md b/docs/helm/helm_upgrade.md index 676c26595..d54b7c3a2 100644 --- a/docs/helm/helm_upgrade.md +++ b/docs/helm/helm_upgrade.md @@ -68,6 +68,7 @@ helm upgrade [RELEASE] [CHART] [flags] --atomic if set, upgrade process rolls back changes made in case of failed upgrade, also sets --wait flag --ca-file string verify certificates of HTTPS-enabled servers using this CA bundle --cert-file string identify HTTPS client using this SSL certificate file + --cleanup-on-fail allow deletion of new resources created in this upgrade when upgrade failed --description string specify the description to use for the upgrade, rather than the default --devel use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored. --dry-run simulate an upgrade @@ -117,4 +118,4 @@ helm upgrade [RELEASE] [CHART] [flags] * [helm](helm.md) - The Helm package manager for Kubernetes. -###### Auto generated by spf13/cobra on 28-Jan-2019 +###### Auto generated by spf13/cobra on 5-Feb-2019 diff --git a/pkg/helm/option.go b/pkg/helm/option.go index 1f5cf6904..930434178 100644 --- a/pkg/helm/option.go +++ b/pkg/helm/option.go @@ -297,6 +297,20 @@ func DeleteDescription(description string) DeleteOption { } } +// UpgradeCleanupOnFail allows deletion of new resources created in this upgrade when upgrade failed +func UpgradeCleanupOnFail(cleanupOnFail bool) UpdateOption { + return func(opts *options) { + opts.updateReq.CleanupOnFail = cleanupOnFail + } +} + +// RollbackCleanupOnFail allows deletion of new resources created in this rollback when rollback failed +func RollbackCleanupOnFail(cleanupOnFail bool) RollbackOption { + return func(opts *options) { + opts.rollbackReq.CleanupOnFail = cleanupOnFail + } +} + // DeleteDisableHooks will disable hooks for a deletion operation. func DeleteDisableHooks(disable bool) DeleteOption { return func(opts *options) { diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 955c75ab1..36cb3f318 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -290,13 +290,33 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) { return buf.String(), nil } -// Update reads in the current configuration and a target configuration from io.reader +// Deprecated; use UpdateWithOptions instead +func (c *Client) Update(namespace string, originalReader, targetReader io.Reader, force bool, recreate bool, timeout int64, shouldWait bool) error { + return c.UpdateWithOptions(namespace, originalReader, targetReader, UpdateOptions{ + Force: force, + Recreate: recreate, + Timeout: timeout, + ShouldWait: shouldWait, + }) +} + +// UpdateOptions provides options to control update behavior +type UpdateOptions struct { + Force bool + Recreate bool + Timeout int64 + ShouldWait bool + // Allow deletion of new resources created in this update when update failed + CleanupOnFail bool +} + +// UpdateWithOptions reads in the current configuration and a target configuration from io.reader // and creates resources that don't already exists, updates resources that have been modified // in the target configuration and deletes resources from the current configuration that are // not present in the target configuration. // // Namespace will set the namespaces. -func (c *Client) Update(namespace string, originalReader, targetReader io.Reader, force bool, recreate bool, timeout int64, shouldWait bool) error { +func (c *Client) UpdateWithOptions(namespace string, originalReader, targetReader io.Reader, opts UpdateOptions) error { original, err := c.BuildUnstructured(namespace, originalReader) if err != nil { return fmt.Errorf("failed decoding reader into objects: %s", err) @@ -308,6 +328,7 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader return fmt.Errorf("failed decoding reader into objects: %s", err) } + newlyCreatedResources := []*resource.Info{} updateErrors := []string{} c.Log("checking %d resources for changes", len(target)) @@ -326,6 +347,7 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader if err := createResource(info); err != nil { return fmt.Errorf("failed to create resource: %s", err) } + newlyCreatedResources = append(newlyCreatedResources, info) kind := info.Mapping.GroupVersionKind.Kind c.Log("Created a new %s called %q\n", kind, info.Name) @@ -338,7 +360,7 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader return fmt.Errorf("no %s with the name %q found", kind, info.Name) } - if err := updateResource(c, info, originalInfo.Object, force, recreate); err != nil { + if err := updateResource(c, info, originalInfo.Object, opts.Force, opts.Recreate); err != nil { c.Log("error updating the resource %q:\n\t %v", info.Name, err) updateErrors = append(updateErrors, err.Error()) } @@ -346,11 +368,27 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader return nil }) + cleanupErrors := []string{} + + if opts.CleanupOnFail { + if err != nil || len(updateErrors) != 0 { + for _, info := range newlyCreatedResources { + kind := info.Mapping.GroupVersionKind.Kind + + c.Log("Deleting newly created %s with the name %q in %s...", kind, info.Name, info.Namespace) + if err := deleteResource(info); err != nil { + c.Log("Error deleting newly created %s with the name %q in %s: %s", kind, info.Name, info.Namespace, err) + cleanupErrors = append(cleanupErrors, err.Error()) + } + } + } + } + switch { case err != nil: - return err + return fmt.Errorf(strings.Join(append([]string{err.Error()}, cleanupErrors...), " && ")) case len(updateErrors) != 0: - return fmt.Errorf(strings.Join(updateErrors, " && ")) + return fmt.Errorf(strings.Join(append(updateErrors, cleanupErrors...), " && ")) } for _, info := range original.Difference(target) { @@ -373,8 +411,8 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader c.Log("Failed to delete %q, err: %s", info.Name, err) } } - if shouldWait { - return c.waitForResources(time.Duration(timeout)*time.Second, target) + if opts.ShouldWait { + return c.waitForResources(time.Duration(opts.Timeout)*time.Second, target) } return nil } diff --git a/pkg/tiller/environment/environment.go b/pkg/tiller/environment/environment.go index 290337d7b..993e27910 100644 --- a/pkg/tiller/environment/environment.go +++ b/pkg/tiller/environment/environment.go @@ -126,14 +126,17 @@ type KubeClient interface { // error. WatchUntilReady(namespace string, reader io.Reader, timeout int64, shouldWait bool) error - // Update updates one or more resources or creates the resource + // Deprecated; use UpdateWithOptions instead + Update(namespace string, originalReader, modifiedReader io.Reader, force bool, recreate bool, timeout int64, shouldWait bool) error + + // UpdateWithOptions updates one or more resources or creates the resource // if it doesn't exist. // // namespace must contain a valid existing namespace. // // reader must contain a YAML stream (one or more YAML documents separated // by "\n---\n"). - Update(namespace string, originalReader, modifiedReader io.Reader, force bool, recreate bool, timeout int64, shouldWait bool) error + UpdateWithOptions(namespace string, originalReader, modifiedReader io.Reader, opts kube.UpdateOptions) error Build(namespace string, reader io.Reader) (kube.Result, error) BuildUnstructured(namespace string, reader io.Reader) (kube.Result, error) @@ -177,6 +180,16 @@ func (p *PrintingKubeClient) WatchUntilReady(ns string, r io.Reader, timeout int // Update implements KubeClient Update. func (p *PrintingKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, force bool, recreate bool, timeout int64, shouldWait bool) error { + return p.UpdateWithOptions(ns, currentReader, modifiedReader, kube.UpdateOptions{ + Force: force, + Recreate: recreate, + Timeout: timeout, + ShouldWait: shouldWait, + }) +} + +// UpdateWithOptions implements KubeClient UpdateWithOptions. +func (p *PrintingKubeClient) UpdateWithOptions(ns string, currentReader, modifiedReader io.Reader, opts kube.UpdateOptions) error { _, err := io.Copy(p.Out, modifiedReader) return err } diff --git a/pkg/tiller/environment/environment_test.go b/pkg/tiller/environment/environment_test.go index 5c19a9b21..c2694a84a 100644 --- a/pkg/tiller/environment/environment_test.go +++ b/pkg/tiller/environment/environment_test.go @@ -52,6 +52,9 @@ func (k *mockKubeClient) Delete(ns string, r io.Reader) error { func (k *mockKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, force bool, recreate bool, timeout int64, shouldWait bool) error { return nil } +func (k *mockKubeClient) UpdateWithOptions(ns string, currentReader, modifiedReader io.Reader, opts kube.UpdateOptions) error { + return nil +} func (k *mockKubeClient) WatchUntilReady(ns string, r io.Reader, timeout int64, shouldWait bool) error { return nil } diff --git a/pkg/tiller/release_modules.go b/pkg/tiller/release_modules.go index 85995480c..360794481 100644 --- a/pkg/tiller/release_modules.go +++ b/pkg/tiller/release_modules.go @@ -58,14 +58,26 @@ func (m *LocalReleaseModule) Create(r *release.Release, req *services.InstallRel func (m *LocalReleaseModule) Update(current, target *release.Release, req *services.UpdateReleaseRequest, env *environment.Environment) error { c := bytes.NewBufferString(current.Manifest) t := bytes.NewBufferString(target.Manifest) - return env.KubeClient.Update(target.Namespace, c, t, req.Force, req.Recreate, req.Timeout, req.Wait) + return env.KubeClient.UpdateWithOptions(target.Namespace, c, t, kube.UpdateOptions{ + Force: req.Force, + Recreate: req.Recreate, + Timeout: req.Timeout, + ShouldWait: req.Wait, + CleanupOnFail: req.CleanupOnFail, + }) } // Rollback performs a rollback from current to target release func (m *LocalReleaseModule) Rollback(current, target *release.Release, req *services.RollbackReleaseRequest, env *environment.Environment) error { c := bytes.NewBufferString(current.Manifest) t := bytes.NewBufferString(target.Manifest) - return env.KubeClient.Update(target.Namespace, c, t, req.Force, req.Recreate, req.Timeout, req.Wait) + return env.KubeClient.UpdateWithOptions(target.Namespace, c, t, kube.UpdateOptions{ + Force: req.Force, + Recreate: req.Recreate, + Timeout: req.Timeout, + ShouldWait: req.Wait, + CleanupOnFail: req.CleanupOnFail, + }) } // Status returns kubectl-like formatted status of release objects diff --git a/pkg/tiller/release_server_test.go b/pkg/tiller/release_server_test.go index 4e29e4413..99fc0e724 100644 --- a/pkg/tiller/release_server_test.go +++ b/pkg/tiller/release_server_test.go @@ -500,6 +500,15 @@ type updateFailingKubeClient struct { } func (u *updateFailingKubeClient) Update(namespace string, originalReader, modifiedReader io.Reader, force bool, recreate bool, timeout int64, shouldWait bool) error { + return u.UpdateWithOptions(namespace, originalReader, modifiedReader, kube.UpdateOptions{ + Force: force, + Recreate: recreate, + Timeout: timeout, + ShouldWait: shouldWait, + }) +} + +func (u *updateFailingKubeClient) UpdateWithOptions(namespace string, originalReader, modifiedReader io.Reader, opts kube.UpdateOptions) error { return errors.New("Failed update in kube client") } @@ -632,6 +641,9 @@ func (kc *mockHooksKubeClient) WatchUntilReady(ns string, r io.Reader, timeout i func (kc *mockHooksKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, force bool, recreate bool, timeout int64, shouldWait bool) error { return nil } +func (kc *mockHooksKubeClient) UpdateWithOptions(ns string, currentReader, modifiedReader io.Reader, opts kube.UpdateOptions) error { + return nil +} func (kc *mockHooksKubeClient) Build(ns string, reader io.Reader) (kube.Result, error) { return []*resource.Info{}, nil } From bf7106f6c0018f3638201752a32529648e253e3e Mon Sep 17 00:00:00 2001 From: Fernando Barbosa Date: Tue, 19 Mar 2019 14:06:33 -0300 Subject: [PATCH 2/4] Add cleanup on fail after wait Signed-off-by: Timofey Kirillov --- pkg/kube/client.go | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 36cb3f318..d5666fedf 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -35,7 +35,7 @@ import ( appsv1beta1 "k8s.io/api/apps/v1beta1" appsv1beta2 "k8s.io/api/apps/v1beta2" batch "k8s.io/api/batch/v1" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" extv1beta1 "k8s.io/api/extensions/v1beta1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" @@ -370,18 +370,8 @@ func (c *Client) UpdateWithOptions(namespace string, originalReader, targetReade cleanupErrors := []string{} - if opts.CleanupOnFail { - if err != nil || len(updateErrors) != 0 { - for _, info := range newlyCreatedResources { - kind := info.Mapping.GroupVersionKind.Kind - - c.Log("Deleting newly created %s with the name %q in %s...", kind, info.Name, info.Namespace) - if err := deleteResource(info); err != nil { - c.Log("Error deleting newly created %s with the name %q in %s: %s", kind, info.Name, info.Namespace, err) - cleanupErrors = append(cleanupErrors, err.Error()) - } - } - } + if opts.CleanupOnFail && (err != nil || len(updateErrors) != 0) { + cleanupErrors = c.cleanup(newlyCreatedResources) } switch { @@ -412,11 +402,30 @@ func (c *Client) UpdateWithOptions(namespace string, originalReader, targetReade } } if opts.ShouldWait { - return c.waitForResources(time.Duration(opts.Timeout)*time.Second, target) + err := c.waitForResources(time.Duration(opts.Timeout)*time.Second, target) + + if opts.CleanupOnFail && err != nil { + cleanupErrors = c.cleanup(newlyCreatedResources) + return fmt.Errorf(strings.Join(append([]string{err.Error()}, cleanupErrors...), " && ")) + } + + return err } return nil } +func (c *Client) cleanup(newlyCreatedResources []*resource.Info) (cleanupErrors []string) { + for _, info := range newlyCreatedResources { + kind := info.Mapping.GroupVersionKind.Kind + c.Log("Deleting newly created %s with the name %q in %s...", kind, info.Name, info.Namespace) + if err := deleteResource(info); err != nil { + c.Log("Error deleting newly created %s with the name %q in %s: %s", kind, info.Name, info.Namespace, err) + cleanupErrors = append(cleanupErrors, err.Error()) + } + } + return +} + // Delete deletes Kubernetes resources from an io.reader. // // Namespace will set the namespace. From faa5fd0b5e312333c6a579b904794b27fc136807 Mon Sep 17 00:00:00 2001 From: Timofey Kirillov Date: Thu, 4 Apr 2019 21:34:26 +0300 Subject: [PATCH 3/4] Add clarification log messages before calling cleanup-on-fail during update Signed-off-by: Timofey Kirillov --- pkg/kube/client.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/kube/client.go b/pkg/kube/client.go index d5666fedf..6e51729cd 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -371,6 +371,7 @@ func (c *Client) UpdateWithOptions(namespace string, originalReader, targetReade cleanupErrors := []string{} if opts.CleanupOnFail && (err != nil || len(updateErrors) != 0) { + c.Log("Cleanup on fail enabled: cleaning up newly created resources due to update manifests failures") cleanupErrors = c.cleanup(newlyCreatedResources) } @@ -405,6 +406,7 @@ func (c *Client) UpdateWithOptions(namespace string, originalReader, targetReade err := c.waitForResources(time.Duration(opts.Timeout)*time.Second, target) if opts.CleanupOnFail && err != nil { + c.Log("Cleanup on fail enabled: cleaning up newly created resources due to wait failure during update") cleanupErrors = c.cleanup(newlyCreatedResources) return fmt.Errorf(strings.Join(append([]string{err.Error()}, cleanupErrors...), " && ")) } From a8145d6f17a7c0fbe9c7b4d16d287cfc5901c232 Mon Sep 17 00:00:00 2001 From: Timofey Kirillov Date: Fri, 22 Mar 2019 21:17:33 +0300 Subject: [PATCH 4/4] Regenerate proto files for `--cleanup-on-fail` option Signed-off-by: Timofey Kirillov --- pkg/proto/hapi/release/status.pb.go | 2 +- pkg/proto/hapi/rudder/rudder.pb.go | 119 +++++++++-------- pkg/proto/hapi/services/tiller.pb.go | 186 +++++++++++++++------------ 3 files changed, 172 insertions(+), 135 deletions(-) diff --git a/pkg/proto/hapi/release/status.pb.go b/pkg/proto/hapi/release/status.pb.go index 284892642..bc75e64b2 100644 --- a/pkg/proto/hapi/release/status.pb.go +++ b/pkg/proto/hapi/release/status.pb.go @@ -20,7 +20,7 @@ const ( Status_UNKNOWN Status_Code = 0 // Status_DEPLOYED indicates that the release has been pushed to Kubernetes. Status_DEPLOYED Status_Code = 1 - // Status_DELETED indicates that a release has been deleted from Kubermetes. + // Status_DELETED indicates that a release has been deleted from Kubernetes. Status_DELETED Status_Code = 2 // Status_SUPERSEDED indicates that this release object is outdated and a newer one exists. Status_SUPERSEDED Status_Code = 3 diff --git a/pkg/proto/hapi/rudder/rudder.pb.go b/pkg/proto/hapi/rudder/rudder.pb.go index 6e26d71eb..3a0de7746 100644 --- a/pkg/proto/hapi/rudder/rudder.pb.go +++ b/pkg/proto/hapi/rudder/rudder.pb.go @@ -214,12 +214,13 @@ func (m *DeleteReleaseResponse) GetResult() *Result { } type UpgradeReleaseRequest struct { - Current *hapi_release5.Release `protobuf:"bytes,1,opt,name=current" json:"current,omitempty"` - Target *hapi_release5.Release `protobuf:"bytes,2,opt,name=target" json:"target,omitempty"` - Timeout int64 `protobuf:"varint,3,opt,name=Timeout" json:"Timeout,omitempty"` - Wait bool `protobuf:"varint,4,opt,name=Wait" json:"Wait,omitempty"` - Recreate bool `protobuf:"varint,5,opt,name=Recreate" json:"Recreate,omitempty"` - Force bool `protobuf:"varint,6,opt,name=Force" json:"Force,omitempty"` + Current *hapi_release5.Release `protobuf:"bytes,1,opt,name=current" json:"current,omitempty"` + Target *hapi_release5.Release `protobuf:"bytes,2,opt,name=target" json:"target,omitempty"` + Timeout int64 `protobuf:"varint,3,opt,name=Timeout" json:"Timeout,omitempty"` + Wait bool `protobuf:"varint,4,opt,name=Wait" json:"Wait,omitempty"` + Recreate bool `protobuf:"varint,5,opt,name=Recreate" json:"Recreate,omitempty"` + Force bool `protobuf:"varint,6,opt,name=Force" json:"Force,omitempty"` + CleanupOnFail bool `protobuf:"varint,7,opt,name=CleanupOnFail" json:"CleanupOnFail,omitempty"` } func (m *UpgradeReleaseRequest) Reset() { *m = UpgradeReleaseRequest{} } @@ -269,6 +270,13 @@ func (m *UpgradeReleaseRequest) GetForce() bool { return false } +func (m *UpgradeReleaseRequest) GetCleanupOnFail() bool { + if m != nil { + return m.CleanupOnFail + } + return false +} + type UpgradeReleaseResponse struct { Release *hapi_release5.Release `protobuf:"bytes,1,opt,name=release" json:"release,omitempty"` Result *Result `protobuf:"bytes,2,opt,name=result" json:"result,omitempty"` @@ -294,12 +302,13 @@ func (m *UpgradeReleaseResponse) GetResult() *Result { } type RollbackReleaseRequest struct { - Current *hapi_release5.Release `protobuf:"bytes,1,opt,name=current" json:"current,omitempty"` - Target *hapi_release5.Release `protobuf:"bytes,2,opt,name=target" json:"target,omitempty"` - Timeout int64 `protobuf:"varint,3,opt,name=Timeout" json:"Timeout,omitempty"` - Wait bool `protobuf:"varint,4,opt,name=Wait" json:"Wait,omitempty"` - Recreate bool `protobuf:"varint,5,opt,name=Recreate" json:"Recreate,omitempty"` - Force bool `protobuf:"varint,6,opt,name=Force" json:"Force,omitempty"` + Current *hapi_release5.Release `protobuf:"bytes,1,opt,name=current" json:"current,omitempty"` + Target *hapi_release5.Release `protobuf:"bytes,2,opt,name=target" json:"target,omitempty"` + Timeout int64 `protobuf:"varint,3,opt,name=Timeout" json:"Timeout,omitempty"` + Wait bool `protobuf:"varint,4,opt,name=Wait" json:"Wait,omitempty"` + Recreate bool `protobuf:"varint,5,opt,name=Recreate" json:"Recreate,omitempty"` + Force bool `protobuf:"varint,6,opt,name=Force" json:"Force,omitempty"` + CleanupOnFail bool `protobuf:"varint,7,opt,name=CleanupOnFail" json:"CleanupOnFail,omitempty"` } func (m *RollbackReleaseRequest) Reset() { *m = RollbackReleaseRequest{} } @@ -349,6 +358,13 @@ func (m *RollbackReleaseRequest) GetForce() bool { return false } +func (m *RollbackReleaseRequest) GetCleanupOnFail() bool { + if m != nil { + return m.CleanupOnFail + } + return false +} + type RollbackReleaseResponse struct { Release *hapi_release5.Release `protobuf:"bytes,1,opt,name=release" json:"release,omitempty"` Result *Result `protobuf:"bytes,2,opt,name=result" json:"result,omitempty"` @@ -680,43 +696,44 @@ var _ReleaseModuleService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("hapi/rudder/rudder.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 597 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x56, 0x5f, 0x8f, 0xd2, 0x4e, - 0x14, 0xa5, 0xb0, 0x14, 0xb8, 0x64, 0x7f, 0x3f, 0x32, 0xa1, 0xd0, 0x34, 0x3e, 0x90, 0x3e, 0x18, - 0xe2, 0xba, 0x25, 0x41, 0x1f, 0x7d, 0x51, 0x96, 0xfd, 0x13, 0x23, 0x9b, 0x0c, 0xe2, 0x26, 0xbe, - 0x75, 0xe1, 0x82, 0xd5, 0xd2, 0xd6, 0xe9, 0x74, 0x1f, 0xd5, 0x4f, 0xe3, 0x57, 0xd2, 0x8f, 0x63, - 0xda, 0x69, 0x89, 0xad, 0xd3, 0x88, 0x6b, 0xc2, 0x83, 0x4f, 0x9d, 0xe9, 0x3d, 0xdc, 0x39, 0xe7, - 0xf4, 0xce, 0x09, 0xa0, 0xbf, 0xb3, 0x03, 0x67, 0xc4, 0xa2, 0xd5, 0x0a, 0x59, 0xfa, 0xb0, 0x02, - 0xe6, 0x73, 0x9f, 0x74, 0xe3, 0x8a, 0x15, 0x22, 0xbb, 0x73, 0x96, 0x18, 0x5a, 0xa2, 0x66, 0xf4, - 0x05, 0x1e, 0x5d, 0xb4, 0x43, 0x1c, 0x39, 0xde, 0xda, 0x17, 0x70, 0xc3, 0xc8, 0x15, 0xd2, 0xa7, - 0xa8, 0x99, 0x2e, 0xa8, 0x14, 0xc3, 0xc8, 0xe5, 0x84, 0xc0, 0x51, 0xfc, 0x1b, 0x5d, 0x19, 0x28, - 0xc3, 0x16, 0x4d, 0xd6, 0xa4, 0x03, 0x35, 0xd7, 0xdf, 0xe8, 0xd5, 0x41, 0x6d, 0xd8, 0xa2, 0xf1, - 0xd2, 0x7c, 0x06, 0xea, 0x9c, 0xdb, 0x3c, 0x0a, 0x49, 0x1b, 0x1a, 0x8b, 0xd9, 0xcb, 0xd9, 0xf5, - 0xcd, 0xac, 0x53, 0x89, 0x37, 0xf3, 0xc5, 0x64, 0x32, 0x9d, 0xcf, 0x3b, 0x0a, 0x39, 0x86, 0xd6, - 0x62, 0x36, 0xb9, 0x7c, 0x3e, 0xbb, 0x98, 0x9e, 0x75, 0xaa, 0xa4, 0x05, 0xf5, 0x29, 0xa5, 0xd7, - 0xb4, 0x53, 0x33, 0xfb, 0xa0, 0xbd, 0x41, 0x16, 0x3a, 0xbe, 0x47, 0x05, 0x0b, 0x8a, 0x1f, 0x23, - 0x0c, 0xb9, 0x79, 0x0e, 0xbd, 0x62, 0x21, 0x0c, 0x7c, 0x2f, 0xc4, 0x98, 0x96, 0x67, 0x6f, 0x31, - 0xa3, 0x15, 0xaf, 0x89, 0x0e, 0x8d, 0x3b, 0x81, 0xd6, 0xab, 0xc9, 0xeb, 0x6c, 0x6b, 0x5e, 0x82, - 0x76, 0xe5, 0x85, 0xdc, 0x76, 0xdd, 0xfc, 0x01, 0x64, 0x04, 0x8d, 0x54, 0x78, 0xd2, 0xa9, 0x3d, - 0xd6, 0xac, 0xc4, 0xc4, 0xcc, 0x8d, 0x0c, 0x9e, 0xa1, 0xcc, 0xcf, 0xd0, 0x2b, 0x76, 0x4a, 0x19, - 0xfd, 0x69, 0x2b, 0xf2, 0x14, 0x54, 0x96, 0x78, 0x9c, 0xb0, 0x6d, 0x8f, 0x1f, 0x58, 0xb2, 0xef, - 0x67, 0x89, 0xef, 0x40, 0x53, 0xac, 0x79, 0x01, 0xdd, 0x33, 0x74, 0x91, 0xe3, 0xdf, 0x2a, 0xf9, - 0x04, 0x5a, 0xa1, 0xd1, 0x61, 0x85, 0x7c, 0x53, 0x40, 0x5b, 0x04, 0x1b, 0x66, 0xaf, 0x24, 0x52, - 0x96, 0x11, 0x63, 0xe8, 0xf1, 0xdf, 0x10, 0x48, 0x51, 0xe4, 0x14, 0x54, 0x6e, 0xb3, 0x0d, 0x66, - 0x04, 0x4a, 0xf0, 0x29, 0x28, 0x9e, 0x93, 0xd7, 0xce, 0x16, 0xfd, 0x88, 0xeb, 0xb5, 0x81, 0x32, - 0xac, 0xd1, 0x6c, 0x1b, 0x4f, 0xd5, 0x8d, 0xed, 0x70, 0xfd, 0x68, 0xa0, 0x0c, 0x9b, 0x34, 0x59, - 0x13, 0x03, 0x9a, 0x14, 0x97, 0x0c, 0x6d, 0x8e, 0x7a, 0x3d, 0x79, 0xbf, 0xdb, 0x93, 0x2e, 0xd4, - 0xcf, 0x7d, 0xb6, 0x44, 0x5d, 0x4d, 0x0a, 0x62, 0x13, 0xcf, 0x48, 0x51, 0xd8, 0x61, 0xad, 0xfd, - 0xae, 0x40, 0x8f, 0xfa, 0xae, 0x7b, 0x6b, 0x2f, 0x3f, 0xfc, 0x63, 0xde, 0x7e, 0x51, 0xa0, 0xff, - 0x8b, 0xb4, 0x83, 0xdf, 0xc0, 0xb4, 0x93, 0x88, 0xbc, 0x7b, 0xdf, 0xc0, 0x00, 0xb4, 0x42, 0xa3, - 0xfb, 0x0a, 0x79, 0x98, 0x86, 0xb4, 0x90, 0x41, 0xf2, 0xe8, 0x2b, 0x6f, 0xed, 0x8b, 0xe0, 0x1e, - 0x7f, 0xad, 0xef, 0xb8, 0xbf, 0xf2, 0x57, 0x91, 0x8b, 0x73, 0x21, 0x95, 0xac, 0xa1, 0x91, 0x06, - 0x2d, 0x39, 0x91, 0x9b, 0x20, 0x0d, 0x68, 0xe3, 0xf1, 0x7e, 0x60, 0xa1, 0xcb, 0xac, 0x90, 0x2d, - 0xfc, 0x97, 0x8f, 0xcf, 0xb2, 0xe3, 0xa4, 0x71, 0x5d, 0x76, 0x9c, 0x3c, 0x91, 0xcd, 0x0a, 0x79, - 0x0f, 0xc7, 0xb9, 0x8c, 0x23, 0x8f, 0xe4, 0x0d, 0x64, 0x89, 0x6a, 0x9c, 0xec, 0x85, 0xdd, 0x9d, - 0x15, 0xc0, 0xff, 0x85, 0xc1, 0x24, 0x25, 0x74, 0xe5, 0x57, 0xd3, 0x38, 0xdd, 0x13, 0xfd, 0xb3, - 0x99, 0xf9, 0x9c, 0x29, 0x33, 0x53, 0x1a, 0xb3, 0x65, 0x66, 0xca, 0xa3, 0x4b, 0x98, 0x99, 0x1b, - 0xd7, 0x32, 0x33, 0x65, 0x97, 0xa3, 0xcc, 0x4c, 0xe9, 0xfc, 0x9b, 0x95, 0x17, 0xcd, 0xb7, 0xaa, - 0x40, 0xdc, 0xaa, 0xc9, 0x1f, 0x92, 0x27, 0x3f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xb6, 0xa5, 0x37, - 0x75, 0xf7, 0x08, 0x00, 0x00, + // 615 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x56, 0x4d, 0x6f, 0xd3, 0x40, + 0x10, 0x8d, 0x9b, 0xc6, 0x69, 0xa6, 0x2a, 0x44, 0xab, 0xba, 0xb5, 0x2c, 0x0e, 0x91, 0x85, 0x50, + 0x44, 0xa9, 0x2b, 0x15, 0x8e, 0x5c, 0x20, 0xfd, 0x14, 0x22, 0x95, 0x36, 0x84, 0x4a, 0xdc, 0xb6, + 0xc9, 0x24, 0x18, 0x36, 0xb6, 0x59, 0xaf, 0x7b, 0x04, 0x7e, 0x0d, 0xff, 0x12, 0x84, 0xec, 0xb5, + 0x23, 0x6c, 0xd6, 0x22, 0x14, 0x29, 0x17, 0x4e, 0xde, 0xd9, 0x79, 0x9d, 0x9d, 0xf7, 0x76, 0xf6, + 0x35, 0x60, 0xbf, 0x67, 0x91, 0x7f, 0x24, 0x92, 0xe9, 0x14, 0x45, 0xfe, 0xf1, 0x22, 0x11, 0xca, + 0x90, 0xec, 0xa6, 0x19, 0x2f, 0x46, 0x71, 0xeb, 0x4f, 0x30, 0xf6, 0x54, 0xce, 0xd9, 0x57, 0x78, + 0xe4, 0xc8, 0x62, 0x3c, 0xf2, 0x83, 0x59, 0xa8, 0xe0, 0x8e, 0x53, 0x4a, 0xe4, 0x5f, 0x95, 0x73, + 0x39, 0x98, 0x14, 0xe3, 0x84, 0x4b, 0x42, 0x60, 0x33, 0xfd, 0x1b, 0xdb, 0xe8, 0x19, 0xfd, 0x0e, + 0xcd, 0xd6, 0xa4, 0x0b, 0x4d, 0x1e, 0xce, 0xed, 0x8d, 0x5e, 0xb3, 0xdf, 0xa1, 0xe9, 0xd2, 0x7d, + 0x0e, 0xe6, 0x48, 0x32, 0x99, 0xc4, 0x64, 0x1b, 0xda, 0xe3, 0xe1, 0xab, 0xe1, 0xd5, 0xf5, 0xb0, + 0xdb, 0x48, 0x83, 0xd1, 0x78, 0x30, 0x38, 0x1d, 0x8d, 0xba, 0x06, 0xd9, 0x81, 0xce, 0x78, 0x38, + 0xb8, 0x78, 0x31, 0x3c, 0x3f, 0x3d, 0xe9, 0x6e, 0x90, 0x0e, 0xb4, 0x4e, 0x29, 0xbd, 0xa2, 0xdd, + 0xa6, 0xbb, 0x0f, 0xd6, 0x5b, 0x14, 0xb1, 0x1f, 0x06, 0x54, 0x75, 0x41, 0xf1, 0x53, 0x82, 0xb1, + 0x74, 0xcf, 0x60, 0xaf, 0x9a, 0x88, 0xa3, 0x30, 0x88, 0x31, 0x6d, 0x2b, 0x60, 0x0b, 0x2c, 0xda, + 0x4a, 0xd7, 0xc4, 0x86, 0xf6, 0xad, 0x42, 0xdb, 0x1b, 0xd9, 0x76, 0x11, 0xba, 0x17, 0x60, 0x5d, + 0x06, 0xb1, 0x64, 0x9c, 0x97, 0x0f, 0x20, 0x47, 0xd0, 0xce, 0x89, 0x67, 0x95, 0xb6, 0x8f, 0x2d, + 0x2f, 0x13, 0xb1, 0x50, 0xa3, 0x80, 0x17, 0x28, 0xf7, 0x0b, 0xec, 0x55, 0x2b, 0xe5, 0x1d, 0xfd, + 0x6d, 0x29, 0xf2, 0x0c, 0x4c, 0x91, 0x69, 0x9c, 0x75, 0xbb, 0x7d, 0xfc, 0xc0, 0xd3, 0xdd, 0x9f, + 0xa7, 0xee, 0x81, 0xe6, 0x58, 0xf7, 0x1c, 0x76, 0x4f, 0x90, 0xa3, 0xc4, 0x7f, 0x65, 0xf2, 0x19, + 0xac, 0x4a, 0xa1, 0xf5, 0x12, 0xf9, 0x6e, 0x80, 0x35, 0x8e, 0xe6, 0x82, 0x4d, 0x35, 0x54, 0x26, + 0x89, 0x10, 0x18, 0xc8, 0x3f, 0x34, 0x90, 0xa3, 0xc8, 0x21, 0x98, 0x92, 0x89, 0x39, 0x16, 0x0d, + 0xd4, 0xe0, 0x73, 0x50, 0x3a, 0x27, 0x6f, 0xfc, 0x05, 0x86, 0x89, 0xb4, 0x9b, 0x3d, 0xa3, 0xdf, + 0xa4, 0x45, 0x98, 0x4e, 0xd5, 0x35, 0xf3, 0xa5, 0xbd, 0xd9, 0x33, 0xfa, 0x5b, 0x34, 0x5b, 0x13, + 0x07, 0xb6, 0x28, 0x4e, 0x04, 0x32, 0x89, 0x76, 0x2b, 0xdb, 0x5f, 0xc6, 0x64, 0x17, 0x5a, 0x67, + 0xa1, 0x98, 0xa0, 0x6d, 0x66, 0x09, 0x15, 0x90, 0x87, 0xb0, 0x33, 0xe0, 0xc8, 0x82, 0x24, 0xba, + 0x0a, 0xce, 0x98, 0xcf, 0xed, 0x76, 0x96, 0x2d, 0x6f, 0xa6, 0x93, 0x54, 0xa5, 0xbf, 0xde, 0x0b, + 0xf8, 0x61, 0xc0, 0x1e, 0x0d, 0x39, 0xbf, 0x61, 0x93, 0x8f, 0xff, 0xe5, 0x0d, 0x7c, 0x35, 0x60, + 0xff, 0x37, 0x01, 0xd6, 0xfe, 0x9a, 0xf3, 0x4a, 0xca, 0x3e, 0xef, 0xfc, 0x9a, 0x23, 0xb0, 0x2a, + 0x85, 0xee, 0x4a, 0xe4, 0x51, 0x6e, 0xf8, 0x8a, 0x06, 0x29, 0xa3, 0x2f, 0x83, 0x59, 0xa8, 0xfe, + 0x09, 0x1c, 0x7f, 0x6b, 0x2d, 0x7b, 0x7f, 0x1d, 0x4e, 0x13, 0x8e, 0x23, 0x45, 0x95, 0xcc, 0xa0, + 0x9d, 0x9b, 0x36, 0x39, 0xd0, 0x8b, 0xa0, 0x35, 0x7b, 0xe7, 0xc9, 0x6a, 0x60, 0xc5, 0xcb, 0x6d, + 0x90, 0x05, 0xdc, 0x2b, 0x5b, 0x71, 0xdd, 0x71, 0x5a, 0xeb, 0xaf, 0x3b, 0x4e, 0xef, 0xee, 0x6e, + 0x83, 0x7c, 0x80, 0x9d, 0x92, 0x5f, 0x92, 0xc7, 0xfa, 0x02, 0x3a, 0x77, 0x76, 0x0e, 0x56, 0xc2, + 0x2e, 0xcf, 0x8a, 0xe0, 0x7e, 0x65, 0x30, 0x49, 0x4d, 0xbb, 0xfa, 0x07, 0xec, 0x1c, 0xae, 0x88, + 0xfe, 0x55, 0xcc, 0xb2, 0x1b, 0xd5, 0x89, 0xa9, 0xb5, 0xec, 0x3a, 0x31, 0xf5, 0x06, 0xa7, 0xc4, + 0x2c, 0x8d, 0x6b, 0x9d, 0x98, 0xba, 0xc7, 0x51, 0x27, 0xa6, 0x76, 0xfe, 0xdd, 0xc6, 0xcb, 0xad, + 0x77, 0xa6, 0x42, 0xdc, 0x98, 0xd9, 0x8f, 0x9b, 0xa7, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe2, + 0x9e, 0x21, 0x0d, 0x43, 0x09, 0x00, 0x00, } diff --git a/pkg/proto/hapi/services/tiller.pb.go b/pkg/proto/hapi/services/tiller.pb.go index ce76cad12..ab6e573e5 100644 --- a/pkg/proto/hapi/services/tiller.pb.go +++ b/pkg/proto/hapi/services/tiller.pb.go @@ -383,6 +383,8 @@ type UpdateReleaseRequest struct { Description string `protobuf:"bytes,12,opt,name=description" json:"description,omitempty"` // Render subchart notes if enabled SubNotes bool `protobuf:"varint,13,opt,name=subNotes" json:"subNotes,omitempty"` + // Allow deletion of new resources created in this update when update failed + CleanupOnFail bool `protobuf:"varint,14,opt,name=cleanup_on_fail,json=cleanupOnFail" json:"cleanup_on_fail,omitempty"` } func (m *UpdateReleaseRequest) Reset() { *m = UpdateReleaseRequest{} } @@ -481,6 +483,13 @@ func (m *UpdateReleaseRequest) GetSubNotes() bool { return false } +func (m *UpdateReleaseRequest) GetCleanupOnFail() bool { + if m != nil { + return m.CleanupOnFail + } + return false +} + // UpdateReleaseResponse is the response to an update request. type UpdateReleaseResponse struct { Release *hapi_release5.Release `protobuf:"bytes,1,opt,name=release" json:"release,omitempty"` @@ -518,6 +527,8 @@ type RollbackReleaseRequest struct { Force bool `protobuf:"varint,8,opt,name=force" json:"force,omitempty"` // Description, if set, will set the description for the rollback Description string `protobuf:"bytes,9,opt,name=description" json:"description,omitempty"` + // Allow deletion of new resources created in this rollback when rollback failed + CleanupOnFail bool `protobuf:"varint,10,opt,name=cleanup_on_fail,json=cleanupOnFail" json:"cleanup_on_fail,omitempty"` } func (m *RollbackReleaseRequest) Reset() { *m = RollbackReleaseRequest{} } @@ -588,6 +599,13 @@ func (m *RollbackReleaseRequest) GetDescription() string { return "" } +func (m *RollbackReleaseRequest) GetCleanupOnFail() bool { + if m != nil { + return m.CleanupOnFail + } + return false +} + // RollbackReleaseResponse is the response to an update request. type RollbackReleaseResponse struct { Release *hapi_release5.Release `protobuf:"bytes,1,opt,name=release" json:"release,omitempty"` @@ -1441,87 +1459,89 @@ var _ReleaseService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("hapi/services/tiller.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1308 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0xed, 0x6e, 0x1b, 0x45, - 0x17, 0x8e, 0xbd, 0xfe, 0x3c, 0x4e, 0xfc, 0xba, 0xd3, 0x34, 0xd9, 0xee, 0x5b, 0x50, 0x58, 0x04, - 0x75, 0x0b, 0x75, 0xc0, 0xf0, 0x07, 0x09, 0x21, 0xa5, 0xae, 0x95, 0x14, 0x82, 0x2b, 0xad, 0xdb, - 0x22, 0x21, 0x21, 0x6b, 0x63, 0x8f, 0xdb, 0xa5, 0xeb, 0x5d, 0xb3, 0x33, 0x1b, 0x9a, 0x1b, 0x40, - 0xe2, 0x27, 0x97, 0x80, 0xc4, 0x85, 0x70, 0x1f, 0xdc, 0x0c, 0x9a, 0xaf, 0xcd, 0xce, 0x7a, 0xd7, - 0x5d, 0xf2, 0x27, 0xde, 0x99, 0x73, 0xe6, 0x7c, 0x3c, 0xcf, 0x9c, 0x33, 0x27, 0x60, 0xbd, 0x76, - 0xd7, 0xde, 0x31, 0xc1, 0xd1, 0xa5, 0x37, 0xc7, 0xe4, 0x98, 0x7a, 0xbe, 0x8f, 0xa3, 0xc1, 0x3a, - 0x0a, 0x69, 0x88, 0xf6, 0x99, 0x6c, 0xa0, 0x64, 0x03, 0x21, 0xb3, 0x0e, 0xf8, 0x89, 0xf9, 0x6b, - 0x37, 0xa2, 0xe2, 0xaf, 0xd0, 0xb6, 0x0e, 0xd3, 0xfb, 0x61, 0xb0, 0xf4, 0x5e, 0x49, 0x81, 0x70, - 0x11, 0x61, 0x1f, 0xbb, 0x04, 0xab, 0x5f, 0xed, 0x90, 0x92, 0x79, 0xc1, 0x32, 0x94, 0x82, 0xff, - 0x6b, 0x02, 0x8a, 0x09, 0x9d, 0x45, 0x71, 0x20, 0x85, 0x77, 0x35, 0x21, 0xa1, 0x2e, 0x8d, 0x89, - 0xe6, 0xec, 0x12, 0x47, 0xc4, 0x0b, 0x03, 0xf5, 0x2b, 0x64, 0xf6, 0xdf, 0x55, 0xb8, 0x7d, 0xee, - 0x11, 0xea, 0x88, 0x83, 0xc4, 0xc1, 0xbf, 0xc4, 0x98, 0x50, 0xb4, 0x0f, 0x75, 0xdf, 0x5b, 0x79, - 0xd4, 0xac, 0x1c, 0x55, 0xfa, 0x86, 0x23, 0x16, 0xe8, 0x00, 0x1a, 0xe1, 0x72, 0x49, 0x30, 0x35, - 0xab, 0x47, 0x95, 0x7e, 0xdb, 0x91, 0x2b, 0xf4, 0x0d, 0x34, 0x49, 0x18, 0xd1, 0xd9, 0xc5, 0x95, - 0x69, 0x1c, 0x55, 0xfa, 0xdd, 0xe1, 0x47, 0x83, 0x3c, 0x9c, 0x06, 0xcc, 0xd3, 0x34, 0x8c, 0xe8, - 0x80, 0xfd, 0x79, 0x7c, 0xe5, 0x34, 0x08, 0xff, 0x65, 0x76, 0x97, 0x9e, 0x4f, 0x71, 0x64, 0xd6, - 0x84, 0x5d, 0xb1, 0x42, 0xa7, 0x00, 0xdc, 0x6e, 0x18, 0x2d, 0x70, 0x64, 0xd6, 0xb9, 0xe9, 0x7e, - 0x09, 0xd3, 0xcf, 0x98, 0xbe, 0xd3, 0x26, 0xea, 0x13, 0x7d, 0x0d, 0xbb, 0x02, 0x92, 0xd9, 0x3c, - 0x5c, 0x60, 0x62, 0x36, 0x8e, 0x8c, 0x7e, 0x77, 0x78, 0x57, 0x98, 0x52, 0xf0, 0x4f, 0x05, 0x68, - 0xa3, 0x70, 0x81, 0x9d, 0x8e, 0x50, 0x67, 0xdf, 0x04, 0xdd, 0x83, 0x76, 0xe0, 0xae, 0x30, 0x59, - 0xbb, 0x73, 0x6c, 0x36, 0x79, 0x84, 0xd7, 0x1b, 0x76, 0x00, 0x2d, 0xe5, 0xdc, 0x7e, 0x0c, 0x0d, - 0x91, 0x1a, 0xea, 0x40, 0xf3, 0xc5, 0xe4, 0xbb, 0xc9, 0xb3, 0x1f, 0x26, 0xbd, 0x1d, 0xd4, 0x82, - 0xda, 0xe4, 0xe4, 0xfb, 0x71, 0xaf, 0x82, 0x6e, 0xc1, 0xde, 0xf9, 0xc9, 0xf4, 0xf9, 0xcc, 0x19, - 0x9f, 0x8f, 0x4f, 0xa6, 0xe3, 0x27, 0xbd, 0x2a, 0xea, 0x02, 0x8c, 0xce, 0x4e, 0x9c, 0xe7, 0x33, - 0xae, 0x62, 0xd8, 0xef, 0x43, 0x3b, 0xc9, 0x01, 0x35, 0xc1, 0x38, 0x99, 0x8e, 0x84, 0x89, 0x27, - 0xe3, 0xe9, 0xa8, 0x57, 0xb1, 0x7f, 0xaf, 0xc0, 0xbe, 0x4e, 0x19, 0x59, 0x87, 0x01, 0xc1, 0x8c, - 0xb3, 0x79, 0x18, 0x07, 0x09, 0x67, 0x7c, 0x81, 0x10, 0xd4, 0x02, 0xfc, 0x56, 0x31, 0xc6, 0xbf, - 0x99, 0x26, 0x0d, 0xa9, 0xeb, 0x73, 0xb6, 0x0c, 0x47, 0x2c, 0xd0, 0xe7, 0xd0, 0x92, 0x50, 0x10, - 0xb3, 0x76, 0x64, 0xf4, 0x3b, 0xc3, 0x3b, 0x3a, 0x40, 0xd2, 0xa3, 0x93, 0xa8, 0xd9, 0xa7, 0x70, - 0x78, 0x8a, 0x55, 0x24, 0x02, 0x3f, 0x75, 0x83, 0x98, 0x5f, 0x77, 0x85, 0x79, 0x30, 0xcc, 0xaf, - 0xbb, 0xc2, 0xc8, 0x84, 0xa6, 0xbc, 0x7e, 0x3c, 0x9c, 0xba, 0xa3, 0x96, 0x36, 0x05, 0x73, 0xd3, - 0x90, 0xcc, 0x2b, 0xcf, 0xd2, 0xc7, 0x50, 0x63, 0x95, 0xc1, 0xcd, 0x74, 0x86, 0x48, 0x8f, 0xf3, - 0x69, 0xb0, 0x0c, 0x1d, 0x2e, 0xd7, 0xa9, 0x33, 0xb2, 0xd4, 0x9d, 0xa5, 0xbd, 0x8e, 0xc2, 0x80, - 0xe2, 0x80, 0xde, 0x2c, 0xfe, 0x73, 0xb8, 0x9b, 0x63, 0x49, 0x26, 0x70, 0x0c, 0x4d, 0x19, 0x1a, - 0xb7, 0x56, 0x88, 0xab, 0xd2, 0xb2, 0xff, 0x34, 0x60, 0xff, 0xc5, 0x7a, 0xe1, 0x52, 0xac, 0x44, - 0x5b, 0x82, 0xba, 0x0f, 0x75, 0xde, 0x61, 0x24, 0x16, 0xb7, 0x84, 0x6d, 0xd1, 0x86, 0x46, 0xec, - 0xaf, 0x23, 0xe4, 0xe8, 0x21, 0x34, 0x2e, 0x5d, 0x3f, 0xc6, 0x84, 0x03, 0x91, 0xa0, 0x26, 0x35, - 0x79, 0x7b, 0x72, 0xa4, 0x06, 0x3a, 0x84, 0xe6, 0x22, 0xba, 0x62, 0xfd, 0x85, 0x97, 0x64, 0xcb, - 0x69, 0x2c, 0xa2, 0x2b, 0x27, 0x0e, 0xd0, 0x87, 0xb0, 0xb7, 0xf0, 0x88, 0x7b, 0xe1, 0xe3, 0xd9, - 0xeb, 0x30, 0x7c, 0x43, 0x78, 0x55, 0xb6, 0x9c, 0x5d, 0xb9, 0x79, 0xc6, 0xf6, 0x90, 0xc5, 0x6e, - 0xd2, 0x3c, 0xc2, 0x2e, 0xc5, 0x66, 0x83, 0xcb, 0x93, 0x35, 0xc3, 0x90, 0x7a, 0x2b, 0x1c, 0xc6, - 0x94, 0x97, 0x92, 0xe1, 0xa8, 0x25, 0xfa, 0x00, 0x76, 0x23, 0x4c, 0x30, 0x9d, 0xc9, 0x28, 0x5b, - 0xfc, 0x64, 0x87, 0xef, 0xbd, 0x14, 0x61, 0x21, 0xa8, 0xfd, 0xea, 0x7a, 0xd4, 0x6c, 0x73, 0x11, - 0xff, 0x16, 0xc7, 0x62, 0x82, 0xd5, 0x31, 0x50, 0xc7, 0x62, 0x82, 0xe5, 0xb1, 0x7d, 0xa8, 0x2f, - 0xc3, 0x68, 0x8e, 0xcd, 0x0e, 0x97, 0x89, 0x05, 0x3a, 0x82, 0xce, 0x02, 0x93, 0x79, 0xe4, 0xad, - 0x29, 0x63, 0x74, 0x97, 0x63, 0x9a, 0xde, 0x62, 0x79, 0x90, 0xf8, 0x62, 0x12, 0x52, 0x4c, 0xcc, - 0x3d, 0x91, 0x87, 0x5a, 0xdb, 0x67, 0x70, 0x27, 0x43, 0xd1, 0x4d, 0xd9, 0xfe, 0xad, 0x0a, 0x07, - 0x4e, 0xe8, 0xfb, 0x17, 0xee, 0xfc, 0x4d, 0x09, 0xbe, 0x53, 0xd4, 0x54, 0xb7, 0x53, 0x63, 0xe4, - 0x50, 0x93, 0xba, 0xc2, 0x35, 0xed, 0x0a, 0x6b, 0xa4, 0xd5, 0x8b, 0x49, 0x6b, 0xe8, 0xa4, 0x29, - 0x46, 0x9a, 0x29, 0x46, 0x12, 0xb8, 0x5b, 0x5b, 0xe0, 0x6e, 0x6f, 0xc0, 0x6d, 0x7f, 0x0b, 0x87, - 0x1b, 0x38, 0xdc, 0x14, 0xd4, 0x3f, 0x0c, 0xb8, 0xf3, 0x34, 0x20, 0xd4, 0xf5, 0xfd, 0x0c, 0xa6, - 0x49, 0xbd, 0x54, 0x4a, 0xd7, 0x4b, 0xf5, 0xbf, 0xd4, 0x8b, 0xa1, 0x91, 0xa2, 0x18, 0xac, 0xa5, - 0x18, 0x2c, 0x55, 0x43, 0x5a, 0xe7, 0x6a, 0x64, 0x3a, 0x17, 0x7a, 0x0f, 0x40, 0x5c, 0x7a, 0x6e, - 0x5c, 0x80, 0xdf, 0xe6, 0x3b, 0x13, 0xd9, 0xa8, 0x14, 0x5f, 0xad, 0x7c, 0xbe, 0xd2, 0x15, 0xd4, - 0x87, 0x9e, 0x8a, 0x67, 0x1e, 0x2d, 0x78, 0x4c, 0xb2, 0x8a, 0xba, 0x72, 0x7f, 0x14, 0x2d, 0x58, - 0x54, 0x59, 0x0e, 0x3b, 0xdb, 0x4b, 0x66, 0x37, 0x53, 0x32, 0x4f, 0xe1, 0x20, 0x4b, 0xc9, 0x4d, - 0xe9, 0xfd, 0xab, 0x02, 0x87, 0x2f, 0x02, 0x2f, 0x97, 0xe0, 0xbc, 0xa2, 0xd9, 0x80, 0xbc, 0x9a, - 0x03, 0xf9, 0x3e, 0xd4, 0xd7, 0x71, 0xf4, 0x0a, 0x4b, 0x0a, 0xc5, 0x22, 0x8d, 0x65, 0x4d, 0xc7, - 0x32, 0x83, 0x46, 0x7d, 0xf3, 0x46, 0xcf, 0xc0, 0xdc, 0x8c, 0xf2, 0x86, 0x39, 0xb3, 0xbc, 0x92, - 0x37, 0xaf, 0x2d, 0xde, 0x37, 0xfb, 0x36, 0xdc, 0x3a, 0xc5, 0xf4, 0xa5, 0x28, 0x61, 0x09, 0x80, - 0x3d, 0x06, 0x94, 0xde, 0xbc, 0xf6, 0x27, 0xb7, 0x74, 0x7f, 0x6a, 0x20, 0x54, 0xfa, 0x4a, 0xcb, - 0xfe, 0x8a, 0xdb, 0x3e, 0xf3, 0x08, 0x0d, 0xa3, 0xab, 0x6d, 0xe0, 0xf6, 0xc0, 0x58, 0xb9, 0x6f, - 0xe5, 0x93, 0xc8, 0x3e, 0xed, 0x53, 0x1e, 0x41, 0x72, 0x54, 0x46, 0x90, 0x1e, 0x30, 0x2a, 0xe5, - 0x06, 0x8c, 0xb7, 0x80, 0x9e, 0xe3, 0x64, 0xd6, 0x79, 0xc7, 0xdb, 0xac, 0x68, 0xaa, 0xea, 0x34, - 0x99, 0xd0, 0x9c, 0xfb, 0xd8, 0x0d, 0xe2, 0xb5, 0x24, 0x56, 0x2d, 0xd9, 0x65, 0x5d, 0xbb, 0x91, - 0xeb, 0xfb, 0xd8, 0x97, 0xcf, 0x5c, 0xb2, 0xb6, 0x7f, 0x82, 0xdb, 0x9a, 0x67, 0x99, 0x03, 0xcb, - 0x95, 0xbc, 0x92, 0x9e, 0xd9, 0x27, 0xfa, 0x12, 0x1a, 0x62, 0x58, 0xe4, 0x7e, 0xbb, 0xc3, 0x7b, - 0x7a, 0x4e, 0xdc, 0x48, 0x1c, 0xc8, 0xe9, 0xd2, 0x91, 0xba, 0xc3, 0x7f, 0x5a, 0xd0, 0x55, 0xe3, - 0x8e, 0x18, 0x65, 0x91, 0x07, 0xbb, 0xe9, 0xb9, 0x0e, 0x3d, 0x28, 0x9e, 0x74, 0x33, 0xe3, 0xba, - 0xf5, 0xb0, 0x8c, 0xaa, 0xc8, 0xc0, 0xde, 0xf9, 0xac, 0x82, 0x08, 0xf4, 0xb2, 0xe3, 0x16, 0x7a, - 0x94, 0x6f, 0xa3, 0x60, 0xbe, 0xb3, 0x06, 0x65, 0xd5, 0x95, 0x5b, 0x74, 0xc9, 0xef, 0x93, 0x3e, - 0x23, 0xa1, 0x77, 0x9a, 0xd1, 0xc7, 0x32, 0xeb, 0xb8, 0xb4, 0x7e, 0xe2, 0xf7, 0x67, 0xd8, 0xd3, - 0x5e, 0x6a, 0x54, 0x80, 0x56, 0xde, 0xc4, 0x65, 0x7d, 0x52, 0x4a, 0x37, 0xf1, 0xb5, 0x82, 0xae, - 0xde, 0xe2, 0x50, 0x81, 0x81, 0xdc, 0xb7, 0xc9, 0xfa, 0xb4, 0x9c, 0x72, 0xe2, 0x8e, 0x40, 0x2f, - 0xdb, 0x5f, 0x8a, 0x78, 0x2c, 0xe8, 0x96, 0x45, 0x3c, 0x16, 0xb5, 0x2d, 0x7b, 0x07, 0xb9, 0x00, - 0xd7, 0xed, 0x05, 0xdd, 0x2f, 0x24, 0x44, 0xef, 0x4a, 0x56, 0xff, 0xdd, 0x8a, 0x89, 0x8b, 0x35, - 0xfc, 0x2f, 0x33, 0x09, 0xa0, 0x02, 0x68, 0xf2, 0x07, 0x27, 0xeb, 0x51, 0x49, 0xed, 0x4c, 0x52, - 0xb2, 0x63, 0x6d, 0x49, 0x4a, 0x6f, 0x87, 0x5b, 0x92, 0xca, 0x34, 0x3f, 0x7b, 0x07, 0x79, 0xd0, - 0x75, 0xe2, 0x40, 0xba, 0x66, 0x6d, 0x01, 0x15, 0x9c, 0xde, 0xec, 0x78, 0xd6, 0x83, 0x12, 0x9a, - 0xd7, 0xf5, 0xfd, 0x18, 0x7e, 0x6c, 0x29, 0xd5, 0x8b, 0x06, 0xff, 0x4f, 0xff, 0x8b, 0x7f, 0x03, - 0x00, 0x00, 0xff, 0xff, 0x30, 0x18, 0x95, 0x9c, 0xd7, 0x10, 0x00, 0x00, + // 1337 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x58, 0xdd, 0x72, 0xdb, 0x44, + 0x14, 0x8e, 0x2d, 0xff, 0x1e, 0x27, 0xae, 0xbb, 0x4d, 0x13, 0xd5, 0x14, 0x26, 0x88, 0xa1, 0x75, + 0x0b, 0x75, 0x20, 0x70, 0xc3, 0x0c, 0xc3, 0x4c, 0xea, 0x86, 0xa4, 0x10, 0xd2, 0x19, 0xb9, 0x2d, + 0x33, 0xcc, 0x30, 0x1e, 0xc5, 0x5e, 0xb7, 0xa2, 0xb2, 0xd6, 0x68, 0x57, 0xa1, 0x79, 0x04, 0x2e, + 0x79, 0x07, 0xae, 0x79, 0x06, 0x6e, 0x79, 0x06, 0x5e, 0x86, 0xd9, 0x3f, 0x45, 0x2b, 0x4b, 0xae, + 0xc8, 0x4d, 0xac, 0xdd, 0x73, 0xf6, 0xfc, 0x7c, 0xdf, 0x9e, 0xb3, 0x67, 0x02, 0xfd, 0xd7, 0xde, + 0xd2, 0xdf, 0xa7, 0x38, 0xba, 0xf0, 0xa7, 0x98, 0xee, 0x33, 0x3f, 0x08, 0x70, 0x34, 0x5c, 0x46, + 0x84, 0x11, 0xb4, 0xcd, 0x65, 0x43, 0x2d, 0x1b, 0x4a, 0x59, 0x7f, 0x47, 0x9c, 0x98, 0xbe, 0xf6, + 0x22, 0x26, 0xff, 0x4a, 0xed, 0xfe, 0x6e, 0x7a, 0x9f, 0x84, 0x73, 0xff, 0x95, 0x12, 0x48, 0x17, + 0x11, 0x0e, 0xb0, 0x47, 0xb1, 0xfe, 0x35, 0x0e, 0x69, 0x99, 0x1f, 0xce, 0x89, 0x12, 0xbc, 0x67, + 0x08, 0x18, 0xa6, 0x6c, 0x12, 0xc5, 0xa1, 0x12, 0xde, 0x31, 0x84, 0x94, 0x79, 0x2c, 0xa6, 0x86, + 0xb3, 0x0b, 0x1c, 0x51, 0x9f, 0x84, 0xfa, 0x57, 0xca, 0x9c, 0xbf, 0xab, 0x70, 0xeb, 0xd4, 0xa7, + 0xcc, 0x95, 0x07, 0xa9, 0x8b, 0x7f, 0x8d, 0x31, 0x65, 0x68, 0x1b, 0xea, 0x81, 0xbf, 0xf0, 0x99, + 0x5d, 0xd9, 0xab, 0x0c, 0x2c, 0x57, 0x2e, 0xd0, 0x0e, 0x34, 0xc8, 0x7c, 0x4e, 0x31, 0xb3, 0xab, + 0x7b, 0x95, 0x41, 0xdb, 0x55, 0x2b, 0xf4, 0x0d, 0x34, 0x29, 0x89, 0xd8, 0xe4, 0xfc, 0xd2, 0xb6, + 0xf6, 0x2a, 0x83, 0xee, 0xc1, 0xc7, 0xc3, 0x3c, 0x9c, 0x86, 0xdc, 0xd3, 0x98, 0x44, 0x6c, 0xc8, + 0xff, 0x3c, 0xbe, 0x74, 0x1b, 0x54, 0xfc, 0x72, 0xbb, 0x73, 0x3f, 0x60, 0x38, 0xb2, 0x6b, 0xd2, + 0xae, 0x5c, 0xa1, 0x63, 0x00, 0x61, 0x97, 0x44, 0x33, 0x1c, 0xd9, 0x75, 0x61, 0x7a, 0x50, 0xc2, + 0xf4, 0x33, 0xae, 0xef, 0xb6, 0xa9, 0xfe, 0x44, 0x5f, 0xc3, 0xa6, 0x84, 0x64, 0x32, 0x25, 0x33, + 0x4c, 0xed, 0xc6, 0x9e, 0x35, 0xe8, 0x1e, 0xdc, 0x91, 0xa6, 0x34, 0xfc, 0x63, 0x09, 0xda, 0x88, + 0xcc, 0xb0, 0xdb, 0x91, 0xea, 0xfc, 0x9b, 0xa2, 0xbb, 0xd0, 0x0e, 0xbd, 0x05, 0xa6, 0x4b, 0x6f, + 0x8a, 0xed, 0xa6, 0x88, 0xf0, 0x6a, 0xc3, 0x09, 0xa1, 0xa5, 0x9d, 0x3b, 0x8f, 0xa1, 0x21, 0x53, + 0x43, 0x1d, 0x68, 0xbe, 0x38, 0xfb, 0xfe, 0xec, 0xd9, 0x8f, 0x67, 0xbd, 0x0d, 0xd4, 0x82, 0xda, + 0xd9, 0xe1, 0x0f, 0x47, 0xbd, 0x0a, 0xba, 0x09, 0x5b, 0xa7, 0x87, 0xe3, 0xe7, 0x13, 0xf7, 0xe8, + 0xf4, 0xe8, 0x70, 0x7c, 0xf4, 0xa4, 0x57, 0x45, 0x5d, 0x80, 0xd1, 0xc9, 0xa1, 0xfb, 0x7c, 0x22, + 0x54, 0x2c, 0xe7, 0x03, 0x68, 0x27, 0x39, 0xa0, 0x26, 0x58, 0x87, 0xe3, 0x91, 0x34, 0xf1, 0xe4, + 0x68, 0x3c, 0xea, 0x55, 0x9c, 0xdf, 0x2b, 0xb0, 0x6d, 0x52, 0x46, 0x97, 0x24, 0xa4, 0x98, 0x73, + 0x36, 0x25, 0x71, 0x98, 0x70, 0x26, 0x16, 0x08, 0x41, 0x2d, 0xc4, 0x6f, 0x35, 0x63, 0xe2, 0x9b, + 0x6b, 0x32, 0xc2, 0xbc, 0x40, 0xb0, 0x65, 0xb9, 0x72, 0x81, 0x3e, 0x87, 0x96, 0x82, 0x82, 0xda, + 0xb5, 0x3d, 0x6b, 0xd0, 0x39, 0xb8, 0x6d, 0x02, 0xa4, 0x3c, 0xba, 0x89, 0x9a, 0x73, 0x0c, 0xbb, + 0xc7, 0x58, 0x47, 0x22, 0xf1, 0xd3, 0x37, 0x88, 0xfb, 0xf5, 0x16, 0x58, 0x04, 0xc3, 0xfd, 0x7a, + 0x0b, 0x8c, 0x6c, 0x68, 0xaa, 0xeb, 0x27, 0xc2, 0xa9, 0xbb, 0x7a, 0xe9, 0x30, 0xb0, 0x57, 0x0d, + 0xa9, 0xbc, 0xf2, 0x2c, 0xdd, 0x83, 0x1a, 0xaf, 0x0c, 0x61, 0xa6, 0x73, 0x80, 0xcc, 0x38, 0x9f, + 0x86, 0x73, 0xe2, 0x0a, 0xb9, 0x49, 0x9d, 0x95, 0xa5, 0xee, 0x24, 0xed, 0x75, 0x44, 0x42, 0x86, + 0x43, 0x76, 0xbd, 0xf8, 0x4f, 0xe1, 0x4e, 0x8e, 0x25, 0x95, 0xc0, 0x3e, 0x34, 0x55, 0x68, 0xc2, + 0x5a, 0x21, 0xae, 0x5a, 0xcb, 0xf9, 0xc7, 0x82, 0xed, 0x17, 0xcb, 0x99, 0xc7, 0xb0, 0x16, 0xad, + 0x09, 0xea, 0x3e, 0xd4, 0x45, 0x87, 0x51, 0x58, 0xdc, 0x94, 0xb6, 0x65, 0x1b, 0x1a, 0xf1, 0xbf, + 0xae, 0x94, 0xa3, 0x87, 0xd0, 0xb8, 0xf0, 0x82, 0x18, 0x53, 0x01, 0x44, 0x82, 0x9a, 0xd2, 0x14, + 0xed, 0xc9, 0x55, 0x1a, 0x68, 0x17, 0x9a, 0xb3, 0xe8, 0x92, 0xf7, 0x17, 0x51, 0x92, 0x2d, 0xb7, + 0x31, 0x8b, 0x2e, 0xdd, 0x38, 0x44, 0x1f, 0xc1, 0xd6, 0xcc, 0xa7, 0xde, 0x79, 0x80, 0x27, 0xaf, + 0x09, 0x79, 0x43, 0x45, 0x55, 0xb6, 0xdc, 0x4d, 0xb5, 0x79, 0xc2, 0xf7, 0x50, 0x9f, 0xdf, 0xa4, + 0x69, 0x84, 0x3d, 0x86, 0xed, 0x86, 0x90, 0x27, 0x6b, 0x8e, 0x21, 0xf3, 0x17, 0x98, 0xc4, 0x4c, + 0x94, 0x92, 0xe5, 0xea, 0x25, 0xfa, 0x10, 0x36, 0x23, 0x4c, 0x31, 0x9b, 0xa8, 0x28, 0x5b, 0xe2, + 0x64, 0x47, 0xec, 0xbd, 0x94, 0x61, 0x21, 0xa8, 0xfd, 0xe6, 0xf9, 0xcc, 0x6e, 0x0b, 0x91, 0xf8, + 0x96, 0xc7, 0x62, 0x8a, 0xf5, 0x31, 0xd0, 0xc7, 0x62, 0x8a, 0xd5, 0xb1, 0x6d, 0xa8, 0xcf, 0x49, + 0x34, 0xc5, 0x76, 0x47, 0xc8, 0xe4, 0x02, 0xed, 0x41, 0x67, 0x86, 0xe9, 0x34, 0xf2, 0x97, 0x8c, + 0x33, 0xba, 0x29, 0x30, 0x4d, 0x6f, 0xf1, 0x3c, 0x68, 0x7c, 0x7e, 0x46, 0x18, 0xa6, 0xf6, 0x96, + 0xcc, 0x43, 0xaf, 0xd1, 0x3d, 0xb8, 0x31, 0x0d, 0xb0, 0x17, 0xc6, 0xcb, 0x09, 0x09, 0x27, 0x73, + 0xcf, 0x0f, 0xec, 0xae, 0x50, 0xd9, 0x52, 0xdb, 0xcf, 0xc2, 0x6f, 0x3d, 0x3f, 0x70, 0x4e, 0xe0, + 0x76, 0x86, 0xca, 0xeb, 0xde, 0x8a, 0xbf, 0xaa, 0xb0, 0xe3, 0x92, 0x20, 0x38, 0xf7, 0xa6, 0x6f, + 0x4a, 0xdc, 0x8b, 0x14, 0x85, 0xd5, 0xf5, 0x14, 0x5a, 0x39, 0x14, 0xa6, 0xae, 0x7a, 0xcd, 0xb8, + 0xea, 0x06, 0xb9, 0xf5, 0x62, 0x72, 0x1b, 0x26, 0xb9, 0x9a, 0xb9, 0x66, 0x8a, 0xb9, 0x84, 0x96, + 0xd6, 0x1a, 0x5a, 0xda, 0xab, 0xb4, 0xe4, 0x40, 0x0f, 0x79, 0xd0, 0x7f, 0x07, 0xbb, 0x2b, 0x78, + 0x5d, 0x17, 0xfc, 0x3f, 0x2c, 0xb8, 0xfd, 0x34, 0xa4, 0xcc, 0x0b, 0x82, 0x0c, 0xf6, 0x49, 0xfd, + 0x55, 0x4a, 0xd7, 0x5f, 0xf5, 0xff, 0xd4, 0x9f, 0x65, 0x90, 0xa7, 0x99, 0xae, 0xa5, 0x98, 0x2e, + 0x55, 0x93, 0x46, 0x27, 0x6c, 0x64, 0x3a, 0x21, 0x7a, 0x1f, 0x40, 0x16, 0x91, 0x30, 0x2e, 0x49, + 0x6a, 0x8b, 0x9d, 0x33, 0xd5, 0xf8, 0x34, 0xaf, 0xad, 0x7c, 0x5e, 0xd3, 0x15, 0x39, 0x80, 0x9e, + 0x8e, 0x67, 0x1a, 0xcd, 0x44, 0x4c, 0x8a, 0xa0, 0xae, 0xda, 0x1f, 0x45, 0x33, 0x1e, 0x55, 0x96, + 0xeb, 0xce, 0xfa, 0x12, 0xdc, 0x34, 0x4b, 0xd0, 0x79, 0x0a, 0x3b, 0x59, 0x4a, 0xae, 0x4b, 0xef, + 0x9f, 0x15, 0xd8, 0x7d, 0x11, 0xfa, 0xb9, 0x04, 0xe7, 0x15, 0xd7, 0x0a, 0xe4, 0xd5, 0x1c, 0xc8, + 0xb7, 0xa1, 0xbe, 0x8c, 0xa3, 0x57, 0x58, 0x51, 0x28, 0x17, 0x69, 0x2c, 0x6b, 0x26, 0x96, 0x19, + 0x34, 0xea, 0x2b, 0x68, 0x38, 0x13, 0xb0, 0x57, 0xa3, 0xbc, 0x66, 0xce, 0x3c, 0xaf, 0xe4, 0x0d, + 0x6d, 0xcb, 0xf7, 0xd2, 0xb9, 0x05, 0x37, 0x8f, 0x31, 0x7b, 0x29, 0x4b, 0x5d, 0x01, 0xe0, 0x1c, + 0x01, 0x4a, 0x6f, 0x5e, 0xf9, 0x53, 0x5b, 0xa6, 0x3f, 0x3d, 0x60, 0x6a, 0x7d, 0xad, 0xe5, 0x7c, + 0x25, 0x6c, 0x9f, 0xf8, 0x94, 0x91, 0xe8, 0x72, 0x1d, 0xb8, 0x3d, 0xb0, 0x16, 0xde, 0x5b, 0xf5, + 0xc4, 0xf2, 0x4f, 0xe7, 0x58, 0x44, 0x90, 0x1c, 0x55, 0x11, 0xa4, 0x07, 0x96, 0x4a, 0xb9, 0x81, + 0xe5, 0x2d, 0xa0, 0xe7, 0x38, 0x99, 0x9d, 0xde, 0xf1, 0xd6, 0x6b, 0x9a, 0xaa, 0x26, 0x4d, 0x36, + 0x34, 0x55, 0x9f, 0x51, 0xc4, 0xea, 0x25, 0xbf, 0xac, 0x4b, 0x2f, 0xf2, 0x82, 0x00, 0x07, 0xea, + 0xd9, 0x4c, 0xd6, 0xce, 0xcf, 0x70, 0xcb, 0xf0, 0xac, 0x72, 0xe0, 0xb9, 0xd2, 0x57, 0xca, 0x33, + 0xff, 0x44, 0x5f, 0x42, 0x43, 0x0e, 0x9f, 0xc2, 0x6f, 0xf7, 0xe0, 0xae, 0x99, 0x93, 0x30, 0x12, + 0x87, 0x6a, 0x5a, 0x75, 0x95, 0xee, 0xc1, 0xbf, 0x2d, 0xe8, 0xea, 0xf1, 0x49, 0x8e, 0xc6, 0xc8, + 0x87, 0xcd, 0xf4, 0x9c, 0x88, 0x1e, 0x14, 0x4f, 0xce, 0x99, 0xf1, 0xbf, 0xff, 0xb0, 0x8c, 0xaa, + 0xcc, 0xc0, 0xd9, 0xf8, 0xac, 0x82, 0x28, 0xf4, 0xb2, 0xe3, 0x1b, 0x7a, 0x94, 0x6f, 0xa3, 0x60, + 0x5e, 0xec, 0x0f, 0xcb, 0xaa, 0x6b, 0xb7, 0xe8, 0x42, 0xdc, 0x27, 0x73, 0xe6, 0x42, 0xef, 0x34, + 0x63, 0x8e, 0x79, 0xfd, 0xfd, 0xd2, 0xfa, 0x89, 0xdf, 0x5f, 0x60, 0xcb, 0x78, 0xd1, 0x51, 0x01, + 0x5a, 0x79, 0x13, 0x5c, 0xff, 0x93, 0x52, 0xba, 0x89, 0xaf, 0x05, 0x74, 0xcd, 0x16, 0x87, 0x0a, + 0x0c, 0xe4, 0xbe, 0x4d, 0xfd, 0x4f, 0xcb, 0x29, 0x27, 0xee, 0x28, 0xf4, 0xb2, 0xfd, 0xa5, 0x88, + 0xc7, 0x82, 0x6e, 0x59, 0xc4, 0x63, 0x51, 0xdb, 0x72, 0x36, 0x90, 0x07, 0x70, 0xd5, 0x5e, 0xd0, + 0xfd, 0x42, 0x42, 0xcc, 0xae, 0xd4, 0x1f, 0xbc, 0x5b, 0x31, 0x71, 0xb1, 0x84, 0x1b, 0x99, 0x49, + 0x00, 0x15, 0x40, 0x93, 0x3f, 0x60, 0xf5, 0x1f, 0x95, 0xd4, 0xce, 0x24, 0xa5, 0x3a, 0xd6, 0x9a, + 0xa4, 0xcc, 0x76, 0xb8, 0x26, 0xa9, 0x4c, 0xf3, 0x73, 0x36, 0x90, 0x0f, 0x5d, 0x37, 0x0e, 0x95, + 0x6b, 0xde, 0x16, 0x50, 0xc1, 0xe9, 0xd5, 0x8e, 0xd7, 0x7f, 0x50, 0x42, 0xf3, 0xaa, 0xbe, 0x1f, + 0xc3, 0x4f, 0x2d, 0xad, 0x7a, 0xde, 0x10, 0xff, 0x39, 0xf8, 0xe2, 0xbf, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x20, 0xcd, 0x9e, 0x3a, 0x27, 0x11, 0x00, 0x00, }