github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/prow/cmd/horologium/main.go (about)

     1  /*
     2  Copyright 2017 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  	"fmt"
    22  	"time"
    23  
    24  	"github.com/sirupsen/logrus"
    25  
    26  	"k8s.io/test-infra/prow/config"
    27  	"k8s.io/test-infra/prow/cron"
    28  	"k8s.io/test-infra/prow/kube"
    29  	"k8s.io/test-infra/prow/logrusutil"
    30  	"k8s.io/test-infra/prow/pjutil"
    31  )
    32  
    33  type options struct {
    34  	configPath    string
    35  	jobConfigPath string
    36  }
    37  
    38  func gatherOptions() options {
    39  	o := options{}
    40  	flag.StringVar(&o.configPath, "config-path", "/etc/config/config.yaml", "Path to config.yaml.")
    41  	flag.StringVar(&o.jobConfigPath, "job-config-path", "", "Path to prow job configs.")
    42  	flag.Parse()
    43  	return o
    44  }
    45  
    46  func main() {
    47  	o := gatherOptions()
    48  	logrus.SetFormatter(
    49  		logrusutil.NewDefaultFieldsFormatter(nil, logrus.Fields{"component": "horologium"}),
    50  	)
    51  
    52  	configAgent := config.Agent{}
    53  	if err := configAgent.Start(o.configPath, o.jobConfigPath); 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).Fatal("Error getting kube client.")
    60  	}
    61  
    62  	// start a cron
    63  	cr := cron.New()
    64  	cr.Start()
    65  
    66  	for now := range time.Tick(1 * time.Minute) {
    67  		start := time.Now()
    68  		if err := sync(kc, configAgent.Config(), cr, now); err != nil {
    69  			logrus.WithError(err).Error("Error syncing periodic jobs.")
    70  		}
    71  		logrus.Infof("Sync time: %v", time.Since(start))
    72  	}
    73  }
    74  
    75  type kubeClient interface {
    76  	ListProwJobs(string) ([]kube.ProwJob, error)
    77  	CreateProwJob(kube.ProwJob) (kube.ProwJob, error)
    78  }
    79  
    80  type cronClient interface {
    81  	SyncConfig(cfg *config.Config) error
    82  	QueuedJobs() []string
    83  }
    84  
    85  func sync(kc kubeClient, cfg *config.Config, cr cronClient, now time.Time) error {
    86  	jobs, err := kc.ListProwJobs(kube.EmptySelector)
    87  	if err != nil {
    88  		return fmt.Errorf("error listing prow jobs: %v", err)
    89  	}
    90  	latestJobs := pjutil.GetLatestProwJobs(jobs, kube.PeriodicJob)
    91  
    92  	if err := cr.SyncConfig(cfg); err != nil {
    93  		logrus.WithError(err).Error("Error syncing cron jobs.")
    94  	}
    95  
    96  	cronTriggers := map[string]bool{}
    97  	for _, job := range cr.QueuedJobs() {
    98  		cronTriggers[job] = true
    99  	}
   100  
   101  	errs := []error{}
   102  	for _, p := range cfg.Periodics {
   103  		j, ok := latestJobs[p.Name]
   104  
   105  		if p.Cron == "" {
   106  			if !ok || (j.Complete() && now.Sub(j.Status.StartTime.Time) > p.GetInterval()) {
   107  				if _, err := kc.CreateProwJob(pjutil.NewProwJob(pjutil.PeriodicSpec(p), p.Labels)); err != nil {
   108  					errs = append(errs, err)
   109  				}
   110  			}
   111  		} else if _, exist := cronTriggers[p.Name]; exist {
   112  			if !ok || j.Complete() {
   113  				if _, err := kc.CreateProwJob(pjutil.NewProwJob(pjutil.PeriodicSpec(p), p.Labels)); err != nil {
   114  					errs = append(errs, err)
   115  				}
   116  			}
   117  		}
   118  	}
   119  
   120  	if len(errs) > 0 {
   121  		return fmt.Errorf("failed to create %d prowjobs: %v", len(errs), errs)
   122  	}
   123  
   124  	return nil
   125  }