github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/prow/cmd/sinker/main_test.go (about) 1 /* 2 Copyright 2016 The Kubernetes 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 main 18 19 import ( 20 "fmt" 21 "strings" 22 "testing" 23 "time" 24 25 "k8s.io/test-infra/prow/config" 26 "k8s.io/test-infra/prow/kube" 27 ) 28 29 type fakeClient struct { 30 Pods []kube.Pod 31 ProwJobs []kube.ProwJob 32 33 DeletedPods []kube.Pod 34 DeletedProwJobs []kube.ProwJob 35 } 36 37 func (c *fakeClient) ListPods(labels map[string]string) ([]kube.Pod, error) { 38 pl := make([]kube.Pod, 0, len(c.Pods)) 39 for _, p := range c.Pods { 40 if labelsMatch(labels, p.Metadata.Labels) { 41 pl = append(pl, p) 42 } 43 } 44 return pl, nil 45 } 46 47 func (c *fakeClient) ListProwJobs(labels map[string]string) ([]kube.ProwJob, error) { 48 jl := make([]kube.ProwJob, 0, len(c.ProwJobs)) 49 for _, j := range c.ProwJobs { 50 if labelsMatch(labels, j.Metadata.Labels) { 51 jl = append(jl, j) 52 } 53 } 54 return jl, nil 55 } 56 57 func (c *fakeClient) DeleteProwJob(name string) error { 58 for i, j := range c.ProwJobs { 59 if j.Metadata.Name == name { 60 c.ProwJobs = append(c.ProwJobs[:i], c.ProwJobs[i+1:]...) 61 c.DeletedProwJobs = append(c.DeletedProwJobs, j) 62 return nil 63 } 64 } 65 return fmt.Errorf("prowjob %s not found", name) 66 } 67 68 func (c *fakeClient) DeletePod(name string) error { 69 for i, p := range c.Pods { 70 if p.Metadata.Name == name { 71 c.Pods = append(c.Pods[:i], c.Pods[i+1:]...) 72 c.DeletedPods = append(c.DeletedPods, p) 73 return nil 74 } 75 } 76 return fmt.Errorf("pod %s not found", name) 77 } 78 79 func labelsMatch(l1 map[string]string, l2 map[string]string) bool { 80 for k1, v1 := range l1 { 81 matched := false 82 for k2, v2 := range l2 { 83 if k1 == k2 && v1 == v2 { 84 matched = true 85 break 86 } 87 } 88 if !matched { 89 return false 90 } 91 } 92 return true 93 } 94 95 const ( 96 maxProwJobAge = 2 * 24 * time.Hour 97 maxPodAge = 12 * time.Hour 98 ) 99 100 type fca struct { 101 c *config.Config 102 } 103 104 func newFakeConfigAgent() *fca { 105 return &fca{ 106 c: &config.Config{ 107 Sinker: config.Sinker{ 108 MaxProwJobAge: maxProwJobAge, 109 MaxPodAge: maxPodAge, 110 }, 111 Periodics: []config.Periodic{ 112 {Name: "retester"}, 113 }, 114 }, 115 } 116 117 } 118 119 func (f *fca) Config() *config.Config { 120 return f.c 121 } 122 123 func TestClean(t *testing.T) { 124 pods := []kube.Pod{ 125 { 126 Metadata: kube.ObjectMeta{ 127 Name: "old-failed", 128 Labels: map[string]string{ 129 kube.CreatedByProw: "true", 130 }, 131 }, 132 Status: kube.PodStatus{ 133 Phase: kube.PodFailed, 134 StartTime: time.Now().Add(-maxPodAge).Add(-time.Second), 135 }, 136 }, 137 { 138 Metadata: kube.ObjectMeta{ 139 Name: "old-succeeded", 140 Labels: map[string]string{ 141 kube.CreatedByProw: "true", 142 }, 143 }, 144 Status: kube.PodStatus{ 145 Phase: kube.PodSucceeded, 146 StartTime: time.Now().Add(-maxPodAge).Add(-time.Second), 147 }, 148 }, 149 { 150 Metadata: kube.ObjectMeta{ 151 Name: "new-failed", 152 Labels: map[string]string{ 153 kube.CreatedByProw: "true", 154 }, 155 }, 156 Status: kube.PodStatus{ 157 Phase: kube.PodFailed, 158 StartTime: time.Now().Add(-10 * time.Second), 159 }, 160 }, 161 { 162 Metadata: kube.ObjectMeta{ 163 Name: "old-running", 164 Labels: map[string]string{ 165 kube.CreatedByProw: "true", 166 }, 167 }, 168 Status: kube.PodStatus{ 169 Phase: kube.PodRunning, 170 StartTime: time.Now().Add(-maxPodAge).Add(-time.Second), 171 }, 172 }, 173 { 174 Metadata: kube.ObjectMeta{ 175 Name: "unrelated-failed", 176 Labels: map[string]string{ 177 kube.CreatedByProw: "not really", 178 }, 179 }, 180 Status: kube.PodStatus{ 181 Phase: kube.PodFailed, 182 StartTime: time.Now().Add(-maxPodAge).Add(-time.Second), 183 }, 184 }, 185 { 186 Metadata: kube.ObjectMeta{ 187 Name: "unrelated-complete", 188 }, 189 Status: kube.PodStatus{ 190 Phase: kube.PodSucceeded, 191 StartTime: time.Now().Add(-maxPodAge).Add(-time.Second), 192 }, 193 }, 194 } 195 deletedPods := []string{ 196 "old-failed", 197 "old-succeeded", 198 } 199 prowJobs := []kube.ProwJob{ 200 { 201 Metadata: kube.ObjectMeta{ 202 Name: "old-complete", 203 }, 204 Status: kube.ProwJobStatus{ 205 StartTime: time.Now().Add(-maxProwJobAge).Add(-time.Second), 206 CompletionTime: time.Now().Add(-time.Second), 207 }, 208 }, 209 { 210 Metadata: kube.ObjectMeta{ 211 Name: "old-incomplete", 212 }, 213 Status: kube.ProwJobStatus{ 214 StartTime: time.Now().Add(-maxProwJobAge).Add(-time.Second), 215 }, 216 }, 217 { 218 Metadata: kube.ObjectMeta{ 219 Name: "new", 220 }, 221 Status: kube.ProwJobStatus{ 222 StartTime: time.Now().Add(-time.Second), 223 }, 224 }, 225 { 226 Metadata: kube.ObjectMeta{ 227 Name: "newer-periodic", 228 }, 229 Spec: kube.ProwJobSpec{ 230 Type: kube.PeriodicJob, 231 Job: "retester", 232 }, 233 Status: kube.ProwJobStatus{ 234 StartTime: time.Now().Add(-maxProwJobAge).Add(-time.Second), 235 CompletionTime: time.Now().Add(-time.Second), 236 }, 237 }, 238 { 239 Metadata: kube.ObjectMeta{ 240 Name: "older-periodic", 241 }, 242 Spec: kube.ProwJobSpec{ 243 Type: kube.PeriodicJob, 244 Job: "retester", 245 }, 246 Status: kube.ProwJobStatus{ 247 StartTime: time.Now().Add(-maxProwJobAge).Add(-time.Minute), 248 CompletionTime: time.Now().Add(-time.Minute), 249 }, 250 }, 251 { 252 Metadata: kube.ObjectMeta{ 253 Name: "oldest-periodic", 254 }, 255 Spec: kube.ProwJobSpec{ 256 Type: kube.PeriodicJob, 257 Job: "retester", 258 }, 259 Status: kube.ProwJobStatus{ 260 StartTime: time.Now().Add(-maxProwJobAge).Add(-time.Hour), 261 CompletionTime: time.Now().Add(-time.Hour), 262 }, 263 }, 264 } 265 deletedProwJobs := []string{ 266 "old-complete", 267 "older-periodic", 268 "oldest-periodic", 269 } 270 kc := &fakeClient{ 271 Pods: pods, 272 ProwJobs: prowJobs, 273 } 274 clean(kc, kc, newFakeConfigAgent()) 275 if len(deletedPods) != len(kc.DeletedPods) { 276 var got []string 277 for _, pj := range kc.DeletedPods { 278 got = append(got, pj.Metadata.Name) 279 } 280 t.Errorf("Deleted wrong number of pods: got %d (%v), expected %d (%v)", 281 len(got), strings.Join(got, ", "), len(deletedPods), strings.Join(deletedPods, ", ")) 282 } 283 for _, n := range deletedPods { 284 found := false 285 for _, p := range kc.DeletedPods { 286 if p.Metadata.Name == n { 287 found = true 288 } 289 } 290 if !found { 291 t.Errorf("Did not delete pod %s", n) 292 } 293 } 294 if len(deletedProwJobs) != len(kc.DeletedProwJobs) { 295 var got []string 296 for _, pj := range kc.DeletedProwJobs { 297 got = append(got, pj.Metadata.Name) 298 } 299 t.Errorf("Deleted wrong number of prowjobs: got %d (%s), expected %d (%s)", 300 len(got), strings.Join(got, ", "), len(deletedProwJobs), strings.Join(deletedProwJobs, ", ")) 301 } 302 for _, n := range deletedProwJobs { 303 found := false 304 for _, j := range kc.DeletedProwJobs { 305 if j.Metadata.Name == n { 306 found = true 307 } 308 } 309 if !found { 310 t.Errorf("Did not delete prowjob %s", n) 311 } 312 } 313 }