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  }