github.com/koderover/helm@v2.17.0+incompatible/pkg/releasetesting/environment.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 releasetesting 18 19 import ( 20 "bytes" 21 "fmt" 22 "io/ioutil" 23 "log" 24 "strings" 25 "sync" 26 "time" 27 28 v1 "k8s.io/api/core/v1" 29 30 "k8s.io/helm/pkg/proto/hapi/release" 31 "k8s.io/helm/pkg/proto/hapi/services" 32 "k8s.io/helm/pkg/tiller/environment" 33 ) 34 35 // logEscaper is necessary for escaping control characters found in the log stream. 36 var logEscaper = strings.NewReplacer("%", "%%") 37 38 // Environment encapsulates information about where test suite executes and returns results 39 type Environment struct { 40 Namespace string 41 KubeClient environment.KubeClient 42 Stream services.ReleaseService_RunReleaseTestServer 43 Timeout int64 44 Parallel bool 45 Parallelism uint32 46 streamLock sync.Mutex 47 } 48 49 func (env *Environment) createTestPod(test *test) error { 50 b := bytes.NewBufferString(test.manifest) 51 if err := env.KubeClient.Create(env.Namespace, b, env.Timeout, false); err != nil { 52 log.Printf(err.Error()) 53 test.result.Info = err.Error() 54 test.result.Status = release.TestRun_FAILURE 55 return err 56 } 57 58 return nil 59 } 60 61 func (env *Environment) getTestPodStatus(test *test) (v1.PodPhase, error) { 62 b := bytes.NewBufferString(test.manifest) 63 status, err := env.KubeClient.WaitAndGetCompletedPodPhase(env.Namespace, b, time.Duration(env.Timeout)*time.Second) 64 if err != nil { 65 log.Printf("Error getting status for pod %s: %s", test.result.Name, err) 66 test.result.Info = err.Error() 67 test.result.Status = release.TestRun_UNKNOWN 68 return status, err 69 } 70 71 return status, err 72 } 73 74 func (env *Environment) streamResult(r *release.TestRun) error { 75 switch r.Status { 76 case release.TestRun_SUCCESS: 77 if err := env.streamSuccess(r.Name); err != nil { 78 return err 79 } 80 case release.TestRun_FAILURE: 81 if err := env.streamFailed(r.Name); err != nil { 82 return err 83 } 84 85 default: 86 if err := env.streamUnknown(r.Name, r.Info); err != nil { 87 return err 88 } 89 } 90 return nil 91 } 92 93 func (env *Environment) streamRunning(name string) error { 94 msg := "RUNNING: " + name 95 return env.streamMessage(msg, release.TestRun_RUNNING) 96 } 97 98 func (env *Environment) streamError(info string) error { 99 msg := "ERROR: " + info 100 return env.streamMessage(msg, release.TestRun_FAILURE) 101 } 102 103 func (env *Environment) streamFailed(name string) error { 104 msg := fmt.Sprintf("FAILED: %s, run `kubectl logs %s --namespace %s` for more info", name, name, env.Namespace) 105 return env.streamMessage(msg, release.TestRun_FAILURE) 106 } 107 108 func (env *Environment) streamSuccess(name string) error { 109 msg := fmt.Sprintf("PASSED: %s", name) 110 return env.streamMessage(msg, release.TestRun_SUCCESS) 111 } 112 113 func (env *Environment) streamUnknown(name, info string) error { 114 msg := fmt.Sprintf("UNKNOWN: %s: %s", name, info) 115 return env.streamMessage(msg, release.TestRun_UNKNOWN) 116 } 117 118 func (env *Environment) streamMessage(msg string, status release.TestRun_Status) error { 119 resp := &services.TestReleaseResponse{Msg: msg, Status: status} 120 env.streamLock.Lock() 121 defer env.streamLock.Unlock() 122 return env.Stream.Send(resp) 123 } 124 125 // DeleteTestPods deletes resources given in testManifests 126 func (env *Environment) DeleteTestPods(testManifests []string) { 127 for _, testManifest := range testManifests { 128 err := env.KubeClient.Delete(env.Namespace, bytes.NewBufferString(testManifest)) 129 if err != nil { 130 env.streamError(err.Error()) 131 } 132 } 133 } 134 135 // GetLogs collects the logs from the pods created in testManifests 136 func (env *Environment) GetLogs(testManifests []string) { 137 for _, testManifest := range testManifests { 138 infos, err := env.KubeClient.Build(env.Namespace, bytes.NewBufferString(testManifest)) 139 if err != nil { 140 env.streamError(err.Error()) 141 continue 142 } 143 if len(infos) == 0 { 144 env.streamError(fmt.Sprint("Pod manifest is invalid. Unable to obtain the logs")) 145 continue 146 } 147 podName := infos[0].Object.(*v1.Pod).Name 148 lr, err := env.KubeClient.GetPodLogs(podName, env.Namespace) 149 if err != nil { 150 env.streamError(err.Error()) 151 continue 152 } 153 logs, err := ioutil.ReadAll(lr) 154 if err != nil { 155 env.streamError(err.Error()) 156 continue 157 } 158 msg := fmt.Sprintf("\nPOD LOGS: %s\n%s", podName, logEscaper.Replace(string(logs))) 159 env.streamMessage(msg, release.TestRun_RUNNING) 160 } 161 }