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 }