github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/service/api_main/apiserver.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"net"
     7  	"net/http"
     8  	"os"
     9  	"time"
    10  
    11  	"github.com/evergreen-ci/evergreen"
    12  	"github.com/evergreen-ci/evergreen/db"
    13  	"github.com/evergreen-ci/evergreen/plugin"
    14  	_ "github.com/evergreen-ci/evergreen/plugin/config"
    15  	"github.com/evergreen-ci/evergreen/service"
    16  	"github.com/evergreen-ci/evergreen/util"
    17  	"github.com/mongodb/grip"
    18  	"github.com/mongodb/grip/level"
    19  	"github.com/mongodb/grip/message"
    20  	"github.com/mongodb/grip/send"
    21  	"gopkg.in/tylerb/graceful.v1"
    22  )
    23  
    24  var (
    25  	// requestTimeout is the duration to wait until killing
    26  	// active requests and stopping the server.
    27  	requestTimeout = 10 * time.Second
    28  )
    29  
    30  func init() {
    31  	flag.Usage = func() {
    32  		fmt.Fprintf(os.Stderr, "%s handles communication with running tasks and command line tools.\n\n", os.Args[0])
    33  		fmt.Fprintf(os.Stderr, "Usage:\n  %s [flags]\n\n", os.Args[0])
    34  		fmt.Fprintf(os.Stderr, "Supported flags are:\n")
    35  		flag.PrintDefaults()
    36  	}
    37  }
    38  
    39  func main() {
    40  	settings := evergreen.GetSettingsOrExit()
    41  
    42  	// setup the logging
    43  	if settings.Api.LogFile != "" {
    44  		sender, err := send.MakeFileLogger(settings.Api.LogFile)
    45  		grip.CatchEmergencyFatal(err)
    46  		defer sender.Close()
    47  		grip.CatchEmergencyFatal(grip.SetSender(sender))
    48  	} else {
    49  		sender := send.MakeNative()
    50  		defer sender.Close()
    51  		grip.CatchEmergencyFatal(grip.SetSender(sender))
    52  	}
    53  	evergreen.SetLegacyLogger()
    54  	grip.SetName("evg-api-server")
    55  	grip.SetDefaultLevel(level.Info)
    56  	grip.SetThreshold(level.Debug)
    57  	grip.Notice(message.Fields{"build": evergreen.BuildRevision, "process": grip.Name()})
    58  
    59  	defer util.RecoverAndLogStackTrace()
    60  
    61  	db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(settings))
    62  
    63  	tlsConfig, err := util.MakeTlsConfig(settings.Api.HttpsCert, settings.Api.HttpsKey)
    64  	if err != nil {
    65  		grip.EmergencyFatalf("Failed to make TLS config: %+v", err)
    66  	}
    67  
    68  	nonSSL, err := service.GetListener(settings.Api.HttpListenAddr)
    69  	if err != nil {
    70  		grip.EmergencyFatalf("Failed to get HTTP listener: %+v", err)
    71  	}
    72  
    73  	ssl, err := service.GetTLSListener(settings.Api.HttpsListenAddr, tlsConfig)
    74  	if err != nil {
    75  		grip.EmergencyFatalf("Failed to get HTTPS listener: %+v", err)
    76  	}
    77  
    78  	// Start SSL and non-SSL servers in independent goroutines, but exit
    79  	// the process if either one fails
    80  	as, err := service.NewAPIServer(settings, plugin.APIPlugins)
    81  	if err != nil {
    82  		grip.EmergencyFatalf("Failed to create API server: %+v", err)
    83  	}
    84  
    85  	handler, err := as.Handler()
    86  	if err != nil {
    87  		grip.EmergencyFatalf("Failed to get API route handlers: %+v", err)
    88  	}
    89  
    90  	server := &http.Server{Handler: handler}
    91  
    92  	errChan := make(chan error, 2)
    93  
    94  	go func() {
    95  		grip.Info("Starting non-SSL API server")
    96  		err := graceful.Serve(server, nonSSL, requestTimeout)
    97  		if err != nil {
    98  			if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
    99  				grip.Warningf("non-SSL API server error: %+v", err)
   100  			} else {
   101  				err = nil
   102  			}
   103  		}
   104  		grip.Info("non-SSL API server cleanly terminated")
   105  		errChan <- err
   106  	}()
   107  
   108  	go func() {
   109  		grip.Info("Starting SSL API server")
   110  		err := graceful.Serve(server, ssl, requestTimeout)
   111  		if err != nil {
   112  			if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
   113  				grip.Warningf("SSL API server error: %+v", err)
   114  			} else {
   115  				err = nil
   116  			}
   117  		}
   118  		grip.Info("SSL API server cleanly terminated")
   119  		errChan <- err
   120  	}()
   121  
   122  	exitCode := 0
   123  
   124  	for i := 0; i < 2; i++ {
   125  		if err := <-errChan; err != nil {
   126  			grip.Errorf("Error returned from API server: %+v", err)
   127  			exitCode = 1
   128  		}
   129  	}
   130  
   131  	os.Exit(exitCode)
   132  }