github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/cmd/sub/main.go (about)

     1  /*
     2  Copyright 2018 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  	"context"
    21  	"flag"
    22  	"net/http"
    23  	"os"
    24  	"os/exec"
    25  	"strconv"
    26  	"time"
    27  
    28  	"github.com/sirupsen/logrus"
    29  
    30  	utilerrors "k8s.io/apimachinery/pkg/util/errors"
    31  	"sigs.k8s.io/prow/pkg/config"
    32  	"sigs.k8s.io/prow/pkg/crier/reporters/pubsub"
    33  	"sigs.k8s.io/prow/pkg/flagutil"
    34  	prowflagutil "sigs.k8s.io/prow/pkg/flagutil"
    35  	configflagutil "sigs.k8s.io/prow/pkg/flagutil/config"
    36  	"sigs.k8s.io/prow/pkg/interrupts"
    37  	"sigs.k8s.io/prow/pkg/logrusutil"
    38  	"sigs.k8s.io/prow/pkg/metrics"
    39  	"sigs.k8s.io/prow/pkg/moonraker"
    40  	"sigs.k8s.io/prow/pkg/pjutil/pprof"
    41  	"sigs.k8s.io/prow/pkg/pubsub/subscriber"
    42  )
    43  
    44  type options struct {
    45  	client         prowflagutil.KubernetesOptions
    46  	github         prowflagutil.GitHubOptions
    47  	port           int
    48  	cookiefilePath string
    49  
    50  	config configflagutil.ConfigOptions
    51  
    52  	dryRun                 bool
    53  	gracePeriod            time.Duration
    54  	instrumentationOptions prowflagutil.InstrumentationOptions
    55  }
    56  
    57  func (o *options) validate() error {
    58  	var errs []error
    59  	for _, group := range []flagutil.OptionGroup{&o.client, &o.github, &o.instrumentationOptions, &o.config} {
    60  		if err := group.Validate(o.dryRun); err != nil {
    61  			errs = append(errs, err)
    62  		}
    63  	}
    64  
    65  	return utilerrors.NewAggregate(errs)
    66  }
    67  
    68  func gatherOptions(fs *flag.FlagSet, args ...string) options {
    69  	var o options
    70  	fs.IntVar(&o.port, "port", 80, "HTTP Port.")
    71  	fs.BoolVar(&o.dryRun, "dry-run", true, "Dry run for testing. Uses API tokens but does not mutate.")
    72  	fs.DurationVar(&o.gracePeriod, "grace-period", 180*time.Second, "On shutdown, try to handle remaining events for the specified duration. ")
    73  	fs.StringVar(&o.cookiefilePath, "cookiefile", "", "Path to git http.cookiefile, leave empty for github or anonymous")
    74  	for _, group := range []flagutil.OptionGroup{&o.client, &o.github, &o.instrumentationOptions, &o.config} {
    75  		group.AddFlags(fs)
    76  	}
    77  
    78  	fs.Parse(args)
    79  
    80  	return o
    81  }
    82  
    83  func main() {
    84  	logrusutil.ComponentInit()
    85  
    86  	o := gatherOptions(flag.NewFlagSet(os.Args[0], flag.ExitOnError), os.Args[1:]...)
    87  	if err := o.validate(); err != nil {
    88  		logrus.WithError(err).Fatal("Invalid options")
    89  	}
    90  
    91  	configAgent, err := o.config.ConfigAgent()
    92  	if err != nil {
    93  		logrus.WithError(err).Fatal("Error starting config agent.")
    94  	}
    95  
    96  	prowjobClient, err := o.client.ProwJobClient(configAgent.Config().ProwJobNamespace, o.dryRun)
    97  	if err != nil {
    98  		logrus.WithError(err).Fatal("unable to create prow job client")
    99  	}
   100  
   101  	promMetrics := subscriber.NewMetrics()
   102  
   103  	defer interrupts.WaitForGracefulShutdown()
   104  
   105  	// Expose prometheus and pprof metrics
   106  	metrics.ExposeMetrics("sub", configAgent.Config().PushGateway, o.instrumentationOptions.MetricsPort)
   107  	pprof.Instrument(o.instrumentationOptions)
   108  
   109  	// If we are provided credentials for Git hosts, use them. These credentials
   110  	// hold per-host information in them so it's safe to set them globally.
   111  	if o.cookiefilePath != "" {
   112  		cmd := exec.Command("git", "config", "--global", "http.cookiefile", o.cookiefilePath)
   113  		if err := cmd.Run(); err != nil {
   114  			logrus.WithError(err).Fatal("unable to set cookiefile")
   115  		}
   116  	}
   117  
   118  	s := &subscriber.Subscriber{
   119  		ConfigAgent:   configAgent,
   120  		Metrics:       promMetrics,
   121  		ProwJobClient: prowjobClient,
   122  		Reporter:      pubsub.NewReporter(configAgent.Config), // reuse crier reporter
   123  	}
   124  
   125  	if o.config.MoonrakerAddress != "" {
   126  		moonrakerClient, err := moonraker.NewClient(o.config.MoonrakerAddress, configAgent)
   127  		if err != nil {
   128  			logrus.WithError(err).Fatal("Error getting Moonraker client.")
   129  		}
   130  		s.InRepoConfigGetter = moonrakerClient
   131  	} else {
   132  		gitClient, err := o.github.GitClientFactory(o.cookiefilePath, &o.config.InRepoConfigCacheDirBase, o.dryRun, false)
   133  		if err != nil {
   134  			logrus.WithError(err).Fatal("Error getting Git client.")
   135  		}
   136  		ircc, err := config.NewInRepoConfigCache(o.config.InRepoConfigCacheSize, configAgent, gitClient)
   137  		if err != nil {
   138  			logrus.WithError(err).Fatal("Error creating InRepoConfigCacheGetter.")
   139  		}
   140  		s.InRepoConfigGetter = ircc
   141  	}
   142  
   143  	subMux := http.NewServeMux()
   144  	// Return 200 on / for health checks.
   145  	subMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {})
   146  
   147  	// Setting up Pull Server
   148  	logrus.Info("Setting up Pull Server")
   149  	pullServer := subscriber.NewPullServer(s)
   150  	interrupts.Run(func(ctx context.Context) {
   151  		if err := pullServer.Run(ctx); err != nil {
   152  			logrus.WithError(err).Fatal("Failed to run Pull Server")
   153  		}
   154  	})
   155  
   156  	httpServer := &http.Server{Addr: ":" + strconv.Itoa(o.port), Handler: subMux}
   157  	interrupts.ListenAndServe(httpServer, o.gracePeriod)
   158  }