github.com/zoumo/helm@v2.5.0+incompatible/pkg/tiller/release_modules.go (about) 1 /* 2 Copyright 2017 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 "bytes" 21 "errors" 22 "fmt" 23 "log" 24 "strings" 25 26 "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" 27 28 "k8s.io/helm/pkg/chartutil" 29 "k8s.io/helm/pkg/kube" 30 "k8s.io/helm/pkg/proto/hapi/release" 31 rudderAPI "k8s.io/helm/pkg/proto/hapi/rudder" 32 "k8s.io/helm/pkg/proto/hapi/services" 33 relutil "k8s.io/helm/pkg/releaseutil" 34 "k8s.io/helm/pkg/rudder" 35 "k8s.io/helm/pkg/tiller/environment" 36 ) 37 38 // ReleaseModule is an interface that allows ReleaseServer to run operations on release via either local implementation or Rudder service 39 type ReleaseModule interface { 40 Create(r *release.Release, req *services.InstallReleaseRequest, env *environment.Environment) error 41 Update(current, target *release.Release, req *services.UpdateReleaseRequest, env *environment.Environment) error 42 Rollback(current, target *release.Release, req *services.RollbackReleaseRequest, env *environment.Environment) error 43 Status(r *release.Release, req *services.GetReleaseStatusRequest, env *environment.Environment) (string, error) 44 Delete(r *release.Release, req *services.UninstallReleaseRequest, env *environment.Environment) (string, []error) 45 } 46 47 // LocalReleaseModule is a local implementation of ReleaseModule 48 type LocalReleaseModule struct { 49 clientset internalclientset.Interface 50 } 51 52 // Create creates a release via kubeclient from provided environment 53 func (m *LocalReleaseModule) Create(r *release.Release, req *services.InstallReleaseRequest, env *environment.Environment) error { 54 b := bytes.NewBufferString(r.Manifest) 55 return env.KubeClient.Create(r.Namespace, b, req.Timeout, req.Wait) 56 } 57 58 // Update performs an update from current to target release 59 func (m *LocalReleaseModule) Update(current, target *release.Release, req *services.UpdateReleaseRequest, env *environment.Environment) error { 60 c := bytes.NewBufferString(current.Manifest) 61 t := bytes.NewBufferString(target.Manifest) 62 return env.KubeClient.Update(target.Namespace, c, t, req.Force, req.Recreate, req.Timeout, req.Wait) 63 } 64 65 // Rollback performs a rollback from current to target release 66 func (m *LocalReleaseModule) Rollback(current, target *release.Release, req *services.RollbackReleaseRequest, env *environment.Environment) error { 67 c := bytes.NewBufferString(current.Manifest) 68 t := bytes.NewBufferString(target.Manifest) 69 return env.KubeClient.Update(target.Namespace, c, t, req.Force, req.Recreate, req.Timeout, req.Wait) 70 } 71 72 // Status returns kubectl-like formatted status of release objects 73 func (m *LocalReleaseModule) Status(r *release.Release, req *services.GetReleaseStatusRequest, env *environment.Environment) (string, error) { 74 return env.KubeClient.Get(r.Namespace, bytes.NewBufferString(r.Manifest)) 75 } 76 77 // Delete deletes the release and returns manifests that were kept in the deletion process 78 func (m *LocalReleaseModule) Delete(rel *release.Release, req *services.UninstallReleaseRequest, env *environment.Environment) (kept string, errs []error) { 79 vs, err := GetVersionSet(m.clientset.Discovery()) 80 if err != nil { 81 return rel.Manifest, []error{fmt.Errorf("Could not get apiVersions from Kubernetes: %v", err)} 82 } 83 return DeleteRelease(rel, vs, env.KubeClient) 84 } 85 86 // RemoteReleaseModule is a ReleaseModule which calls Rudder service to operate on a release 87 type RemoteReleaseModule struct{} 88 89 // Create calls rudder.InstallRelease 90 func (m *RemoteReleaseModule) Create(r *release.Release, req *services.InstallReleaseRequest, env *environment.Environment) error { 91 request := &rudderAPI.InstallReleaseRequest{Release: r} 92 _, err := rudder.InstallRelease(request) 93 return err 94 } 95 96 // Update calls rudder.UpgradeRelease 97 func (m *RemoteReleaseModule) Update(current, target *release.Release, req *services.UpdateReleaseRequest, env *environment.Environment) error { 98 upgrade := &rudderAPI.UpgradeReleaseRequest{ 99 Current: current, 100 Target: target, 101 Recreate: req.Recreate, 102 Timeout: req.Timeout, 103 Wait: req.Wait, 104 Force: req.Force, 105 } 106 _, err := rudder.UpgradeRelease(upgrade) 107 return err 108 } 109 110 // Rollback calls rudder.Rollback 111 func (m *RemoteReleaseModule) Rollback(current, target *release.Release, req *services.RollbackReleaseRequest, env *environment.Environment) error { 112 rollback := &rudderAPI.RollbackReleaseRequest{ 113 Current: current, 114 Target: target, 115 Recreate: req.Recreate, 116 Timeout: req.Timeout, 117 Wait: req.Wait, 118 } 119 _, err := rudder.RollbackRelease(rollback) 120 return err 121 } 122 123 // Status returns status retrieved from rudder.ReleaseStatus 124 func (m *RemoteReleaseModule) Status(r *release.Release, req *services.GetReleaseStatusRequest, env *environment.Environment) (string, error) { 125 statusRequest := &rudderAPI.ReleaseStatusRequest{Release: r} 126 resp, err := rudder.ReleaseStatus(statusRequest) 127 return resp.Info.Status.Resources, err 128 } 129 130 // Delete calls rudder.DeleteRelease 131 func (m *RemoteReleaseModule) Delete(r *release.Release, req *services.UninstallReleaseRequest, env *environment.Environment) (string, []error) { 132 deleteRequest := &rudderAPI.DeleteReleaseRequest{Release: r} 133 resp, err := rudder.DeleteRelease(deleteRequest) 134 if err != nil { 135 return resp.Release.Manifest, []error{err} 136 } 137 return resp.Release.Manifest, []error{} 138 } 139 140 // DeleteRelease is a helper that allows Rudder to delete a release without exposing most of Tiller inner functions 141 func DeleteRelease(rel *release.Release, vs chartutil.VersionSet, kubeClient environment.KubeClient) (kept string, errs []error) { 142 manifests := relutil.SplitManifests(rel.Manifest) 143 _, files, err := sortManifests(manifests, vs, UninstallOrder) 144 if err != nil { 145 // We could instead just delete everything in no particular order. 146 // FIXME: One way to delete at this point would be to try a label-based 147 // deletion. The problem with this is that we could get a false positive 148 // and delete something that was not legitimately part of this release. 149 return rel.Manifest, []error{fmt.Errorf("corrupted release record. You must manually delete the resources: %s", err)} 150 } 151 152 filesToKeep, filesToDelete := filterManifestsToKeep(files) 153 if len(filesToKeep) > 0 { 154 kept = summarizeKeptManifests(filesToKeep) 155 } 156 157 errs = []error{} 158 for _, file := range filesToDelete { 159 b := bytes.NewBufferString(strings.TrimSpace(file.content)) 160 if b.Len() == 0 { 161 continue 162 } 163 if err := kubeClient.Delete(rel.Namespace, b); err != nil { 164 log.Printf("uninstall: Failed deletion of %q: %s", rel.Name, err) 165 if err == kube.ErrNoObjectsVisited { 166 // Rewrite the message from "no objects visited" 167 err = errors.New("object not found, skipping delete") 168 } 169 errs = append(errs, err) 170 } 171 } 172 return kept, errs 173 }