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  }