github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/prow/cmd/sinker/main.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 "flag" 21 "time" 22 23 "github.com/sirupsen/logrus" 24 25 "k8s.io/test-infra/prow/config" 26 "k8s.io/test-infra/prow/kube" 27 "k8s.io/test-infra/prow/pjutil" 28 ) 29 30 type kubeClient interface { 31 ListPods(labels map[string]string) ([]kube.Pod, error) 32 DeletePod(name string) error 33 34 ListProwJobs(labels map[string]string) ([]kube.ProwJob, error) 35 DeleteProwJob(name string) error 36 } 37 38 type configAgent interface { 39 Config() *config.Config 40 } 41 42 var ( 43 runOnce = flag.Bool("run-once", false, "If true, run only once then quit.") 44 configPath = flag.String("config-path", "/etc/config/config", "Path to config.yaml.") 45 cluster = flag.String("build-cluster", "", "Path to kube.Cluster YAML file. If empty, uses the local cluster.") 46 ) 47 48 func main() { 49 flag.Parse() 50 logrus.SetFormatter(&logrus.JSONFormatter{}) 51 52 configAgent := &config.Agent{} 53 if err := configAgent.Start(*configPath); err != nil { 54 logrus.WithError(err).Fatal("Error starting config agent.") 55 } 56 57 kc, err := kube.NewClientInCluster(configAgent.Config().ProwJobNamespace) 58 if err != nil { 59 logrus.WithError(err).Error("Error getting client.") 60 return 61 } 62 63 var pkc *kube.Client 64 if *cluster == "" { 65 pkc = kc.Namespace(configAgent.Config().PodNamespace) 66 } else { 67 pkc, err = kube.NewClientFromFile(*cluster, configAgent.Config().PodNamespace) 68 if err != nil { 69 logrus.WithError(err).Fatal("Error getting kube client.") 70 } 71 } 72 73 logger := logrus.StandardLogger() 74 kc.Logger = logger.WithField("client", "kube") 75 pkc.Logger = logger.WithField("client", "kube") 76 77 // Clean now and regularly from now on. 78 for { 79 start := time.Now() 80 clean(kc, pkc, configAgent) 81 logrus.Infof("Sync time: %v", time.Since(start)) 82 if *runOnce { 83 break 84 } 85 time.Sleep(configAgent.Config().Sinker.ResyncPeriod) 86 } 87 } 88 89 func clean(kc, pkc kubeClient, configAgent configAgent) { 90 // Clean up old prow jobs first. 91 prowJobs, err := kc.ListProwJobs(nil) 92 if err != nil { 93 logrus.WithError(err).Error("Error listing prow jobs.") 94 return 95 } 96 maxProwJobAge := configAgent.Config().Sinker.MaxProwJobAge 97 for _, prowJob := range prowJobs { 98 // Handle periodics separately. 99 if prowJob.Spec.Type == kube.PeriodicJob { 100 continue 101 } 102 if prowJob.Complete() && time.Since(prowJob.Status.StartTime) > maxProwJobAge { 103 if err := kc.DeleteProwJob(prowJob.Metadata.Name); err == nil { 104 logrus.WithField("prowjob", prowJob.Metadata.Name).Info("Deleted prowjob.") 105 } else { 106 logrus.WithField("prowjob", prowJob.Metadata.Name).WithError(err).Error("Error deleting prowjob.") 107 } 108 } 109 } 110 111 // Keep track of what periodic jobs are in the config so we will 112 // not clean up their last prowjob. 113 isActivePeriodic := make(map[string]bool) 114 for _, p := range configAgent.Config().Periodics { 115 isActivePeriodic[p.Name] = true 116 } 117 // Get the jobs that we need to retain so horologium can continue working 118 // as intended. 119 latestPeriodics := pjutil.GetLatestPeriodics(prowJobs) 120 for _, prowJob := range prowJobs { 121 if prowJob.Spec.Type != kube.PeriodicJob { 122 continue 123 } 124 125 latestPJ := latestPeriodics[prowJob.Spec.Job] 126 if isActivePeriodic[prowJob.Spec.Job] && prowJob.Metadata.Name == latestPJ.Metadata.Name { 127 // Ignore deleting this one. 128 continue 129 } 130 if prowJob.Complete() && time.Since(prowJob.Status.StartTime) > maxProwJobAge { 131 if err := kc.DeleteProwJob(prowJob.Metadata.Name); err == nil { 132 logrus.WithField("prowjob", prowJob.Metadata.Name).Info("Deleted prowjob.") 133 } else { 134 logrus.WithField("prowjob", prowJob.Metadata.Name).WithError(err).Error("Error deleting prowjob.") 135 } 136 } 137 } 138 139 // Now clean up old pods. 140 labels := map[string]string{kube.CreatedByProw: "true"} 141 pods, err := pkc.ListPods(labels) 142 if err != nil { 143 logrus.WithError(err).Error("Error listing pods.") 144 return 145 } 146 maxPodAge := configAgent.Config().Sinker.MaxPodAge 147 for _, pod := range pods { 148 if (pod.Status.Phase == kube.PodSucceeded || pod.Status.Phase == kube.PodFailed) && 149 time.Since(pod.Status.StartTime) > maxPodAge { 150 // Delete old completed pods. Don't quit if we fail to delete one. 151 if err := pkc.DeletePod(pod.Metadata.Name); err == nil { 152 logrus.WithField("pod", pod.Metadata.Name).Info("Deleted old completed pod.") 153 } else { 154 logrus.WithField("pod", pod.Metadata.Name).WithError(err).Error("Error deleting pod.") 155 } 156 } 157 } 158 }