github.com/azlyth/helm@v2.8.2+incompatible/pkg/helm/fake.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 helm // import "k8s.io/helm/pkg/helm" 18 19 import ( 20 "errors" 21 "fmt" 22 "math/rand" 23 "sync" 24 25 "github.com/golang/protobuf/ptypes/timestamp" 26 "k8s.io/helm/pkg/proto/hapi/chart" 27 "k8s.io/helm/pkg/proto/hapi/release" 28 rls "k8s.io/helm/pkg/proto/hapi/services" 29 "k8s.io/helm/pkg/proto/hapi/version" 30 ) 31 32 // FakeClient implements Interface 33 type FakeClient struct { 34 Rels []*release.Release 35 Responses map[string]release.TestRun_Status 36 Opts options 37 } 38 39 // Option returns the fake release client 40 func (c *FakeClient) Option(opts ...Option) Interface { 41 for _, opt := range opts { 42 opt(&c.Opts) 43 } 44 return c 45 } 46 47 var _ Interface = &FakeClient{} 48 var _ Interface = (*FakeClient)(nil) 49 50 // ListReleases lists the current releases 51 func (c *FakeClient) ListReleases(opts ...ReleaseListOption) (*rls.ListReleasesResponse, error) { 52 resp := &rls.ListReleasesResponse{ 53 Count: int64(len(c.Rels)), 54 Releases: c.Rels, 55 } 56 return resp, nil 57 } 58 59 // InstallRelease creates a new release and returns a InstallReleaseResponse containing that release 60 func (c *FakeClient) InstallRelease(chStr, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) { 61 chart := &chart.Chart{} 62 return c.InstallReleaseFromChart(chart, ns, opts...) 63 } 64 65 // InstallReleaseFromChart adds a new MockRelease to the fake client and returns a InstallReleaseResponse containing that release 66 func (c *FakeClient) InstallReleaseFromChart(chart *chart.Chart, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) { 67 for _, opt := range opts { 68 opt(&c.Opts) 69 } 70 71 releaseName := c.Opts.instReq.Name 72 73 // Check to see if the release already exists. 74 rel, err := c.ReleaseStatus(releaseName, nil) 75 if err == nil && rel != nil { 76 return nil, errors.New("cannot re-use a name that is still in use") 77 } 78 79 release := ReleaseMock(&MockReleaseOptions{Name: releaseName, Namespace: ns}) 80 c.Rels = append(c.Rels, release) 81 82 return &rls.InstallReleaseResponse{ 83 Release: release, 84 }, nil 85 } 86 87 // DeleteRelease deletes a release from the FakeClient 88 func (c *FakeClient) DeleteRelease(rlsName string, opts ...DeleteOption) (*rls.UninstallReleaseResponse, error) { 89 for i, rel := range c.Rels { 90 if rel.Name == rlsName { 91 c.Rels = append(c.Rels[:i], c.Rels[i+1:]...) 92 return &rls.UninstallReleaseResponse{ 93 Release: rel, 94 }, nil 95 } 96 } 97 98 return nil, fmt.Errorf("No such release: %s", rlsName) 99 } 100 101 // GetVersion returns a fake version 102 func (c *FakeClient) GetVersion(opts ...VersionOption) (*rls.GetVersionResponse, error) { 103 return &rls.GetVersionResponse{ 104 Version: &version.Version{ 105 SemVer: "1.2.3-fakeclient+testonly", 106 }, 107 }, nil 108 } 109 110 // UpdateRelease returns an UpdateReleaseResponse containing the updated release, if it exists 111 func (c *FakeClient) UpdateRelease(rlsName string, chStr string, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) { 112 return c.UpdateReleaseFromChart(rlsName, &chart.Chart{}, opts...) 113 } 114 115 // UpdateReleaseFromChart returns an UpdateReleaseResponse containing the updated release, if it exists 116 func (c *FakeClient) UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) { 117 // Check to see if the release already exists. 118 rel, err := c.ReleaseContent(rlsName, nil) 119 if err != nil { 120 return nil, err 121 } 122 123 return &rls.UpdateReleaseResponse{Release: rel.Release}, nil 124 } 125 126 // RollbackRelease returns nil, nil 127 func (c *FakeClient) RollbackRelease(rlsName string, opts ...RollbackOption) (*rls.RollbackReleaseResponse, error) { 128 return nil, nil 129 } 130 131 // ReleaseStatus returns a release status response with info from the matching release name. 132 func (c *FakeClient) ReleaseStatus(rlsName string, opts ...StatusOption) (*rls.GetReleaseStatusResponse, error) { 133 for _, rel := range c.Rels { 134 if rel.Name == rlsName { 135 return &rls.GetReleaseStatusResponse{ 136 Name: rel.Name, 137 Info: rel.Info, 138 Namespace: rel.Namespace, 139 }, nil 140 } 141 } 142 return nil, fmt.Errorf("No such release: %s", rlsName) 143 } 144 145 // ReleaseContent returns the configuration for the matching release name in the fake release client. 146 func (c *FakeClient) ReleaseContent(rlsName string, opts ...ContentOption) (resp *rls.GetReleaseContentResponse, err error) { 147 for _, rel := range c.Rels { 148 if rel.Name == rlsName { 149 return &rls.GetReleaseContentResponse{ 150 Release: rel, 151 }, nil 152 } 153 } 154 return resp, fmt.Errorf("No such release: %s", rlsName) 155 } 156 157 // ReleaseHistory returns a release's revision history. 158 func (c *FakeClient) ReleaseHistory(rlsName string, opts ...HistoryOption) (*rls.GetHistoryResponse, error) { 159 return &rls.GetHistoryResponse{Releases: c.Rels}, nil 160 } 161 162 // RunReleaseTest executes a pre-defined tests on a release 163 func (c *FakeClient) RunReleaseTest(rlsName string, opts ...ReleaseTestOption) (<-chan *rls.TestReleaseResponse, <-chan error) { 164 165 results := make(chan *rls.TestReleaseResponse) 166 errc := make(chan error, 1) 167 168 go func() { 169 var wg sync.WaitGroup 170 for m, s := range c.Responses { 171 wg.Add(1) 172 173 go func(msg string, status release.TestRun_Status) { 174 defer wg.Done() 175 results <- &rls.TestReleaseResponse{Msg: msg, Status: status} 176 }(m, s) 177 } 178 179 wg.Wait() 180 close(results) 181 close(errc) 182 }() 183 184 return results, errc 185 } 186 187 // PingTiller pings the Tiller pod and ensure's that it is up and runnning 188 func (c *FakeClient) PingTiller() error { 189 return nil 190 } 191 192 // MockHookTemplate is the hook template used for all mock release objects. 193 var MockHookTemplate = `apiVersion: v1 194 kind: Job 195 metadata: 196 annotations: 197 "helm.sh/hooks": pre-install 198 ` 199 200 // MockManifest is the manifest used for all mock release objects. 201 var MockManifest = `apiVersion: v1 202 kind: Secret 203 metadata: 204 name: fixture 205 ` 206 207 // MockReleaseOptions allows for user-configurable options on mock release objects. 208 type MockReleaseOptions struct { 209 Name string 210 Version int32 211 Chart *chart.Chart 212 StatusCode release.Status_Code 213 Namespace string 214 } 215 216 // ReleaseMock creates a mock release object based on options set by MockReleaseOptions. This function should typically not be used outside of testing. 217 func ReleaseMock(opts *MockReleaseOptions) *release.Release { 218 date := timestamp.Timestamp{Seconds: 242085845, Nanos: 0} 219 220 name := opts.Name 221 if name == "" { 222 name = "testrelease-" + string(rand.Intn(100)) 223 } 224 225 var version int32 = 1 226 if opts.Version != 0 { 227 version = opts.Version 228 } 229 230 namespace := opts.Namespace 231 if namespace == "" { 232 namespace = "default" 233 } 234 235 ch := opts.Chart 236 if opts.Chart == nil { 237 ch = &chart.Chart{ 238 Metadata: &chart.Metadata{ 239 Name: "foo", 240 Version: "0.1.0-beta.1", 241 }, 242 Templates: []*chart.Template{ 243 {Name: "templates/foo.tpl", Data: []byte(MockManifest)}, 244 }, 245 } 246 } 247 248 scode := release.Status_DEPLOYED 249 if opts.StatusCode > 0 { 250 scode = opts.StatusCode 251 } 252 253 return &release.Release{ 254 Name: name, 255 Info: &release.Info{ 256 FirstDeployed: &date, 257 LastDeployed: &date, 258 Status: &release.Status{Code: scode}, 259 Description: "Release mock", 260 }, 261 Chart: ch, 262 Config: &chart.Config{Raw: `name: "value"`}, 263 Version: version, 264 Namespace: namespace, 265 Hooks: []*release.Hook{ 266 { 267 Name: "pre-install-hook", 268 Kind: "Job", 269 Path: "pre-install-hook.yaml", 270 Manifest: MockHookTemplate, 271 LastRun: &date, 272 Events: []release.Hook_Event{release.Hook_PRE_INSTALL}, 273 }, 274 }, 275 Manifest: MockManifest, 276 } 277 }