github.com/darkowlzz/helm@v2.5.1-0.20171213183701-6707fe0468d4+incompatible/pkg/tiller/release_rollback.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors All rights reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package tiller 18 19 import ( 20 "fmt" 21 22 ctx "golang.org/x/net/context" 23 24 "k8s.io/helm/pkg/hooks" 25 "k8s.io/helm/pkg/proto/hapi/release" 26 "k8s.io/helm/pkg/proto/hapi/services" 27 "k8s.io/helm/pkg/timeconv" 28 ) 29 30 // RollbackRelease rolls back to a previous version of the given release. 31 func (s *ReleaseServer) RollbackRelease(c ctx.Context, req *services.RollbackReleaseRequest) (*services.RollbackReleaseResponse, error) { 32 s.Log("preparing rollback of %s", req.Name) 33 currentRelease, targetRelease, err := s.prepareRollback(req) 34 if err != nil { 35 return nil, err 36 } 37 38 if !req.DryRun { 39 s.Log("creating rolled back release for %s", req.Name) 40 if err := s.env.Releases.Create(targetRelease); err != nil { 41 return nil, err 42 } 43 } 44 s.Log("performing rollback of %s", req.Name) 45 res, err := s.performRollback(currentRelease, targetRelease, req) 46 if err != nil { 47 return res, err 48 } 49 50 if !req.DryRun { 51 s.Log("updating status for rolled back release for %s", req.Name) 52 if err := s.env.Releases.Update(targetRelease); err != nil { 53 return res, err 54 } 55 } 56 57 return res, nil 58 } 59 60 // prepareRollback finds the previous release and prepares a new release object with 61 // the previous release's configuration 62 func (s *ReleaseServer) prepareRollback(req *services.RollbackReleaseRequest) (*release.Release, *release.Release, error) { 63 if err := validateReleaseName(req.Name); err != nil { 64 s.Log("prepareRollback: Release name is invalid: %s", req.Name) 65 return nil, nil, err 66 } 67 68 if req.Version < 0 { 69 return nil, nil, errInvalidRevision 70 } 71 72 crls, err := s.env.Releases.Last(req.Name) 73 if err != nil { 74 return nil, nil, err 75 } 76 77 rbv := req.Version 78 if req.Version == 0 { 79 rbv = crls.Version - 1 80 } 81 82 s.Log("rolling back %s (current: v%d, target: v%d)", req.Name, crls.Version, rbv) 83 84 prls, err := s.env.Releases.Get(req.Name, rbv) 85 if err != nil { 86 return nil, nil, err 87 } 88 89 // Store a new release object with previous release's configuration 90 target := &release.Release{ 91 Name: req.Name, 92 Namespace: crls.Namespace, 93 Chart: prls.Chart, 94 Config: prls.Config, 95 Info: &release.Info{ 96 FirstDeployed: crls.Info.FirstDeployed, 97 LastDeployed: timeconv.Now(), 98 Status: &release.Status{ 99 Code: release.Status_PENDING_ROLLBACK, 100 Notes: prls.Info.Status.Notes, 101 }, 102 // Because we lose the reference to rbv elsewhere, we set the 103 // message here, and only override it later if we experience failure. 104 Description: fmt.Sprintf("Rollback to %d", rbv), 105 }, 106 Version: crls.Version + 1, 107 Manifest: prls.Manifest, 108 Hooks: prls.Hooks, 109 } 110 111 return crls, target, nil 112 } 113 114 func (s *ReleaseServer) performRollback(currentRelease, targetRelease *release.Release, req *services.RollbackReleaseRequest) (*services.RollbackReleaseResponse, error) { 115 res := &services.RollbackReleaseResponse{Release: targetRelease} 116 117 if req.DryRun { 118 s.Log("dry run for %s", targetRelease.Name) 119 return res, nil 120 } 121 122 // pre-rollback hooks 123 if !req.DisableHooks { 124 if err := s.execHook(targetRelease.Hooks, targetRelease.Name, targetRelease.Namespace, hooks.PreRollback, req.Timeout); err != nil { 125 return res, err 126 } 127 } else { 128 s.Log("rollback hooks disabled for %s", req.Name) 129 } 130 131 if err := s.ReleaseModule.Rollback(currentRelease, targetRelease, req, s.env); err != nil { 132 msg := fmt.Sprintf("Rollback %q failed: %s", targetRelease.Name, err) 133 s.Log("warning: %s", msg) 134 currentRelease.Info.Status.Code = release.Status_SUPERSEDED 135 targetRelease.Info.Status.Code = release.Status_FAILED 136 targetRelease.Info.Description = msg 137 s.recordRelease(currentRelease, true) 138 s.recordRelease(targetRelease, false) 139 return res, err 140 } 141 142 // post-rollback hooks 143 if !req.DisableHooks { 144 if err := s.execHook(targetRelease.Hooks, targetRelease.Name, targetRelease.Namespace, hooks.PostRollback, req.Timeout); err != nil { 145 return res, err 146 } 147 } 148 149 currentRelease.Info.Status.Code = release.Status_SUPERSEDED 150 s.recordRelease(currentRelease, true) 151 152 targetRelease.Info.Status.Code = release.Status_DEPLOYED 153 154 return res, nil 155 }