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