github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/testserver/server.go (about)

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package testserver
     5  
     6  import (
     7  	"crypto/tls"
     8  	"fmt"
     9  	"net"
    10  	"net/http"
    11  	"net/http/httptest"
    12  
    13  	"github.com/juju/clock"
    14  	jc "github.com/juju/testing/checkers"
    15  	gc "gopkg.in/check.v1"
    16  	"gopkg.in/juju/names.v2"
    17  
    18  	"github.com/juju/juju/api"
    19  	"github.com/juju/juju/apiserver"
    20  	"github.com/juju/juju/apiserver/apiserverhttp"
    21  	"github.com/juju/juju/apiserver/observer"
    22  	"github.com/juju/juju/apiserver/observer/fakeobserver"
    23  	"github.com/juju/juju/apiserver/stateauthenticator"
    24  	"github.com/juju/juju/core/auditlog"
    25  	"github.com/juju/juju/core/cache"
    26  	"github.com/juju/juju/core/presence"
    27  	"github.com/juju/juju/pubsub/centralhub"
    28  	"github.com/juju/juju/state"
    29  	coretesting "github.com/juju/juju/testing"
    30  	"github.com/juju/juju/worker/lease"
    31  )
    32  
    33  // DefaultServerConfig returns the default configuration for starting a test server.
    34  func DefaultServerConfig(c *gc.C) apiserver.ServerConfig {
    35  	fakeOrigin := names.NewMachineTag("0")
    36  	hub := centralhub.New(fakeOrigin)
    37  	return apiserver.ServerConfig{
    38  		Clock:           clock.WallClock,
    39  		Tag:             names.NewMachineTag("0"),
    40  		LogDir:          c.MkDir(),
    41  		Hub:             hub,
    42  		Controller:      &cache.Controller{}, // Not useful for anything except providing a default.
    43  		Presence:        presence.New(clock.WallClock),
    44  		LeaseManager:    &lease.Manager{},
    45  		NewObserver:     func() observer.Observer { return &fakeobserver.Instance{} },
    46  		RateLimitConfig: apiserver.DefaultRateLimitConfig(),
    47  		GetAuditConfig:  func() auditlog.Config { return auditlog.Config{Enabled: false} },
    48  		UpgradeComplete: func() bool { return true },
    49  		RestoreStatus: func() state.RestoreStatus {
    50  			return state.RestoreNotActive
    51  		},
    52  		MetricsCollector: apiserver.NewMetricsCollector(),
    53  	}
    54  }
    55  
    56  // NewServer returns a new running API server using the given state.
    57  // The pool may be nil, in which case a pool using the given state
    58  // will be used.
    59  //
    60  // It returns information suitable for connecting to the state
    61  // without any authentication information or model tag, and the server
    62  // that's been started.
    63  func NewServer(c *gc.C, statePool *state.StatePool, controller *cache.Controller) *Server {
    64  	config := DefaultServerConfig(c)
    65  	config.Controller = controller
    66  	return NewServerWithConfig(c, statePool, config)
    67  }
    68  
    69  // NewServerWithConfig is like NewServer except that the entire
    70  // server configuration may be specified (see DefaultServerConfig
    71  // for a suitable starting point).
    72  func NewServerWithConfig(c *gc.C, statePool *state.StatePool, cfg apiserver.ServerConfig) *Server {
    73  	// Note that we can't listen on localhost here because TestAPIServerCanListenOnBothIPv4AndIPv6 assumes
    74  	// that we listen on IPv6 too, and listening on localhost does not do that.
    75  	listener, err := net.Listen("tcp", ":0")
    76  	c.Assert(err, jc.ErrorIsNil)
    77  	certPool, err := api.CreateCertPool(coretesting.CACert)
    78  	if err != nil {
    79  		c.Fatalf(err.Error())
    80  	}
    81  	tlsConfig := api.NewTLSConfig(certPool)
    82  	tlsConfig.ServerName = "juju-apiserver"
    83  	tlsConfig.Certificates = []tls.Certificate{*coretesting.ServerTLSCert}
    84  	mux := apiserverhttp.NewMux()
    85  	httpServer := &httptest.Server{
    86  		Listener: listener,
    87  		Config:   &http.Server{Handler: mux},
    88  		TLS:      tlsConfig,
    89  	}
    90  
    91  	cfg.Mux = mux
    92  	cfg.StatePool = statePool
    93  
    94  	if cfg.Authenticator == nil {
    95  		authenticator, err := stateauthenticator.NewAuthenticator(statePool, cfg.Clock)
    96  		c.Assert(err, jc.ErrorIsNil)
    97  		cfg.Authenticator = authenticator
    98  	}
    99  
   100  	if cfg.MetricsCollector == nil {
   101  		cfg.MetricsCollector = apiserver.NewMetricsCollector()
   102  	}
   103  
   104  	srv, err := apiserver.NewServer(cfg)
   105  	c.Assert(err, jc.ErrorIsNil)
   106  	httpServer.StartTLS()
   107  
   108  	return &Server{
   109  		APIServer:  srv,
   110  		HTTPServer: httpServer,
   111  		Info: &api.Info{
   112  			Addrs:  []string{fmt.Sprintf("localhost:%d", listener.Addr().(*net.TCPAddr).Port)},
   113  			CACert: coretesting.CACert,
   114  		},
   115  	}
   116  }
   117  
   118  // Server wraps both the HTTP and API servers needed to test API
   119  // interactions and simplifies managing their lifecycles.
   120  type Server struct {
   121  	APIServer  *apiserver.Server
   122  	HTTPServer *httptest.Server
   123  	Info       *api.Info
   124  }
   125  
   126  // Stop stops both the API and HTTP servers.
   127  func (s *Server) Stop() error {
   128  	s.HTTPServer.Close()
   129  	return s.APIServer.Stop()
   130  }