github.com/canthefason/helm@v2.2.1-0.20170221172616-16b043b8d505+incompatible/pkg/releasetesting/test_suite_test.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 releasetesting 18 19 import ( 20 "io" 21 "os" 22 "testing" 23 "time" 24 25 "github.com/golang/protobuf/ptypes/timestamp" 26 "golang.org/x/net/context" 27 grpc "google.golang.org/grpc" 28 "google.golang.org/grpc/metadata" 29 "k8s.io/kubernetes/pkg/api" 30 31 "k8s.io/helm/pkg/helm" 32 "k8s.io/helm/pkg/proto/hapi/chart" 33 "k8s.io/helm/pkg/proto/hapi/release" 34 "k8s.io/helm/pkg/proto/hapi/services" 35 "k8s.io/helm/pkg/storage" 36 "k8s.io/helm/pkg/storage/driver" 37 tillerEnv "k8s.io/helm/pkg/tiller/environment" 38 ) 39 40 const manifestWithTestSuccessHook = ` 41 apiVersion: v1 42 kind: Pod 43 metadata: 44 name: finding-nemo, 45 annotations: 46 "helm.sh/hook": test-success 47 spec: 48 containers: 49 - name: nemo-test 50 image: fake-image 51 cmd: fake-command 52 ` 53 54 const manifestWithTestFailureHook = ` 55 apiVersion: v1 56 kind: Pod 57 metadata: 58 name: gold-rush, 59 annotations: 60 "helm.sh/hook": test-failure 61 spec: 62 containers: 63 - name: gold-finding-test 64 image: fake-gold-finding-image 65 cmd: fake-gold-finding-command 66 ` 67 const manifestWithInstallHooks = `apiVersion: v1 68 kind: ConfigMap 69 metadata: 70 name: test-cm 71 annotations: 72 "helm.sh/hook": post-install,pre-delete 73 data: 74 name: value 75 ` 76 77 func TestNewTestSuite(t *testing.T) { 78 rel := releaseStub() 79 80 _, err := NewTestSuite(rel) 81 if err != nil { 82 t.Errorf("%s", err) 83 } 84 } 85 86 func TestRun(t *testing.T) { 87 88 testManifests := []string{manifestWithTestSuccessHook, manifestWithTestFailureHook} 89 ts := testSuiteFixture(testManifests) 90 if err := ts.Run(testEnvFixture()); err != nil { 91 t.Errorf("%s", err) 92 } 93 94 if ts.StartedAt == nil { 95 t.Errorf("Expected StartedAt to not be nil. Got: %v", ts.StartedAt) 96 } 97 98 if ts.CompletedAt == nil { 99 t.Errorf("Expected CompletedAt to not be nil. Got: %v", ts.CompletedAt) 100 } 101 102 if len(ts.Results) != 2 { 103 t.Errorf("Expected 2 test result. Got %v", len(ts.Results)) 104 } 105 106 result := ts.Results[0] 107 if result.StartedAt == nil { 108 t.Errorf("Expected test StartedAt to not be nil. Got: %v", result.StartedAt) 109 } 110 111 if result.CompletedAt == nil { 112 t.Errorf("Expected test CompletedAt to not be nil. Got: %v", result.CompletedAt) 113 } 114 115 if result.Name != "finding-nemo" { 116 t.Errorf("Expected test name to be finding-nemo. Got: %v", result.Name) 117 } 118 119 if result.Status != release.TestRun_SUCCESS { 120 t.Errorf("Expected test result to be successful, got: %v", result.Status) 121 } 122 123 result2 := ts.Results[1] 124 if result2.StartedAt == nil { 125 t.Errorf("Expected test StartedAt to not be nil. Got: %v", result2.StartedAt) 126 } 127 128 if result2.CompletedAt == nil { 129 t.Errorf("Expected test CompletedAt to not be nil. Got: %v", result2.CompletedAt) 130 } 131 132 if result2.Name != "gold-rush" { 133 t.Errorf("Expected test name to be gold-rush, Got: %v", result2.Name) 134 } 135 136 if result2.Status != release.TestRun_FAILURE { 137 t.Errorf("Expected test result to be successful, got: %v", result2.Status) 138 } 139 140 } 141 142 func TestRunSuccessWithTestFailureHook(t *testing.T) { 143 ts := testSuiteFixture([]string{manifestWithTestFailureHook}) 144 env := testEnvFixture() 145 env.KubeClient = newPodFailedKubeClient() 146 if err := ts.Run(env); err != nil { 147 t.Errorf("%s", err) 148 } 149 150 if ts.StartedAt == nil { 151 t.Errorf("Expected StartedAt to not be nil. Got: %v", ts.StartedAt) 152 } 153 154 if ts.CompletedAt == nil { 155 t.Errorf("Expected CompletedAt to not be nil. Got: %v", ts.CompletedAt) 156 } 157 158 if len(ts.Results) != 1 { 159 t.Errorf("Expected 1 test result. Got %v", len(ts.Results)) 160 } 161 162 result := ts.Results[0] 163 if result.StartedAt == nil { 164 t.Errorf("Expected test StartedAt to not be nil. Got: %v", result.StartedAt) 165 } 166 167 if result.CompletedAt == nil { 168 t.Errorf("Expected test CompletedAt to not be nil. Got: %v", result.CompletedAt) 169 } 170 171 if result.Name != "gold-rush" { 172 t.Errorf("Expected test name to be gold-rush, Got: %v", result.Name) 173 } 174 175 if result.Status != release.TestRun_SUCCESS { 176 t.Errorf("Expected test result to be successful, got: %v", result.Status) 177 } 178 } 179 180 func TestExtractTestManifestsFromHooks(t *testing.T) { 181 rel := releaseStub() 182 testManifests, err := extractTestManifestsFromHooks(rel.Hooks) 183 if err != nil { 184 t.Errorf("Expected no error, Got: %s", err) 185 } 186 187 if len(testManifests) != 1 { 188 t.Errorf("Expected 1 test manifest, Got: %v", len(testManifests)) 189 } 190 } 191 192 func chartStub() *chart.Chart { 193 return &chart.Chart{ 194 Metadata: &chart.Metadata{ 195 Name: "nemo", 196 }, 197 Templates: []*chart.Template{ 198 {Name: "templates/hello", Data: []byte("hello: world")}, 199 {Name: "templates/hooks", Data: []byte(manifestWithTestSuccessHook)}, 200 }, 201 } 202 } 203 204 func releaseStub() *release.Release { 205 date := timestamp.Timestamp{Seconds: 242085845, Nanos: 0} 206 return &release.Release{ 207 Name: "lost-fish", 208 Info: &release.Info{ 209 FirstDeployed: &date, 210 LastDeployed: &date, 211 Status: &release.Status{Code: release.Status_DEPLOYED}, 212 Description: "a release stub", 213 }, 214 Chart: chartStub(), 215 Config: &chart.Config{Raw: `name: value`}, 216 Version: 1, 217 Hooks: []*release.Hook{ 218 { 219 Name: "finding-nemo", 220 Kind: "Pod", 221 Path: "finding-nemo", 222 Manifest: manifestWithTestSuccessHook, 223 Events: []release.Hook_Event{ 224 release.Hook_RELEASE_TEST_SUCCESS, 225 }, 226 }, 227 { 228 Name: "test-cm", 229 Kind: "ConfigMap", 230 Path: "test-cm", 231 Manifest: manifestWithInstallHooks, 232 Events: []release.Hook_Event{ 233 release.Hook_POST_INSTALL, 234 release.Hook_PRE_DELETE, 235 }, 236 }, 237 }, 238 } 239 } 240 241 func testFixture() *test { 242 return &test{ 243 manifest: manifestWithTestSuccessHook, 244 result: &release.TestRun{}, 245 } 246 } 247 248 func testSuiteFixture(testManifests []string) *TestSuite { 249 if len(testManifests) == 0 { 250 testManifests = []string{manifestWithTestSuccessHook, manifestWithTestFailureHook} 251 } 252 testResults := []*release.TestRun{} 253 ts := &TestSuite{ 254 TestManifests: testManifests, 255 Results: testResults, 256 } 257 258 return ts 259 } 260 261 func testEnvFixture() *Environment { 262 return newMockTestingEnvironment().Environment 263 } 264 265 func mockTillerEnvironment() *tillerEnv.Environment { 266 e := tillerEnv.New() 267 e.Releases = storage.Init(driver.NewMemory()) 268 e.KubeClient = newPodSucceededKubeClient() 269 return e 270 } 271 272 type mockStream struct { 273 stream grpc.ServerStream 274 messages []*services.TestReleaseResponse 275 } 276 277 func (rs mockStream) Send(m *services.TestReleaseResponse) error { 278 rs.messages = append(rs.messages, m) 279 return nil 280 } 281 func (rs mockStream) SetHeader(m metadata.MD) error { return nil } 282 func (rs mockStream) SendHeader(m metadata.MD) error { return nil } 283 func (rs mockStream) SetTrailer(m metadata.MD) {} 284 func (rs mockStream) SendMsg(v interface{}) error { return nil } 285 func (rs mockStream) RecvMsg(v interface{}) error { return nil } 286 func (rs mockStream) Context() context.Context { return helm.NewContext() } 287 288 type podSucceededKubeClient struct { 289 tillerEnv.PrintingKubeClient 290 } 291 292 func newPodSucceededKubeClient() *podSucceededKubeClient { 293 return &podSucceededKubeClient{ 294 PrintingKubeClient: tillerEnv.PrintingKubeClient{Out: os.Stdout}, 295 } 296 } 297 298 func (p *podSucceededKubeClient) WaitAndGetCompletedPodPhase(ns string, r io.Reader, timeout time.Duration) (api.PodPhase, error) { 299 return api.PodSucceeded, nil 300 } 301 302 type podFailedKubeClient struct { 303 tillerEnv.PrintingKubeClient 304 } 305 306 func newPodFailedKubeClient() *podFailedKubeClient { 307 return &podFailedKubeClient{ 308 PrintingKubeClient: tillerEnv.PrintingKubeClient{Out: os.Stdout}, 309 } 310 } 311 312 func (p *podFailedKubeClient) WaitAndGetCompletedPodPhase(ns string, r io.Reader, timeout time.Duration) (api.PodPhase, error) { 313 return api.PodFailed, nil 314 }