github.com/darkowlzz/helm@v2.5.1-0.20171213183701-6707fe0468d4+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 // MockHookTemplate is the hook template used for all mock release objects. 188 var MockHookTemplate = `apiVersion: v1 189 kind: Job 190 metadata: 191 annotations: 192 "helm.sh/hooks": pre-install 193 ` 194 195 // MockManifest is the manifest used for all mock release objects. 196 var MockManifest = `apiVersion: v1 197 kind: Secret 198 metadata: 199 name: fixture 200 ` 201 202 // MockReleaseOptions allows for user-configurable options on mock release objects. 203 type MockReleaseOptions struct { 204 Name string 205 Version int32 206 Chart *chart.Chart 207 StatusCode release.Status_Code 208 Namespace string 209 } 210 211 // ReleaseMock creates a mock release object based on options set by MockReleaseOptions. This function should typically not be used outside of testing. 212 func ReleaseMock(opts *MockReleaseOptions) *release.Release { 213 date := timestamp.Timestamp{Seconds: 242085845, Nanos: 0} 214 215 name := opts.Name 216 if name == "" { 217 name = "testrelease-" + string(rand.Intn(100)) 218 } 219 220 var version int32 = 1 221 if opts.Version != 0 { 222 version = opts.Version 223 } 224 225 namespace := opts.Namespace 226 if namespace == "" { 227 namespace = "default" 228 } 229 230 ch := opts.Chart 231 if opts.Chart == nil { 232 ch = &chart.Chart{ 233 Metadata: &chart.Metadata{ 234 Name: "foo", 235 Version: "0.1.0-beta.1", 236 }, 237 Templates: []*chart.Template{ 238 {Name: "templates/foo.tpl", Data: []byte(MockManifest)}, 239 }, 240 } 241 } 242 243 scode := release.Status_DEPLOYED 244 if opts.StatusCode > 0 { 245 scode = opts.StatusCode 246 } 247 248 return &release.Release{ 249 Name: name, 250 Info: &release.Info{ 251 FirstDeployed: &date, 252 LastDeployed: &date, 253 Status: &release.Status{Code: scode}, 254 Description: "Release mock", 255 }, 256 Chart: ch, 257 Config: &chart.Config{Raw: `name: "value"`}, 258 Version: version, 259 Namespace: namespace, 260 Hooks: []*release.Hook{ 261 { 262 Name: "pre-install-hook", 263 Kind: "Job", 264 Path: "pre-install-hook.yaml", 265 Manifest: MockHookTemplate, 266 LastRun: &date, 267 Events: []release.Hook_Event{release.Hook_PRE_INSTALL}, 268 }, 269 }, 270 Manifest: MockManifest, 271 } 272 }