github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/httpserver/manifold_test.go (about)

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package httpserver_test
     5  
     6  import (
     7  	"crypto/tls"
     8  	"time"
     9  
    10  	"github.com/juju/clock/testclock"
    11  	"github.com/juju/errors"
    12  	"github.com/juju/pubsub"
    13  	"github.com/juju/testing"
    14  	jc "github.com/juju/testing/checkers"
    15  	gc "gopkg.in/check.v1"
    16  	"gopkg.in/juju/worker.v1"
    17  	"gopkg.in/juju/worker.v1/dependency"
    18  	dt "gopkg.in/juju/worker.v1/dependency/testing"
    19  	"gopkg.in/juju/worker.v1/workertest"
    20  
    21  	"github.com/juju/juju/apiserver/apiserverhttp"
    22  	"github.com/juju/juju/controller"
    23  	"github.com/juju/juju/state"
    24  	"github.com/juju/juju/worker/httpserver"
    25  )
    26  
    27  type ManifoldSuite struct {
    28  	testing.IsolationSuite
    29  
    30  	config               httpserver.ManifoldConfig
    31  	manifold             dependency.Manifold
    32  	context              dependency.Context
    33  	state                stubStateTracker
    34  	hub                  *pubsub.StructuredHub
    35  	mux                  *apiserverhttp.Mux
    36  	clock                *testclock.Clock
    37  	prometheusRegisterer stubPrometheusRegisterer
    38  	certWatcher          stubCertWatcher
    39  	tlsConfig            *tls.Config
    40  	controllerConfig     controller.Config
    41  
    42  	stub testing.Stub
    43  }
    44  
    45  var _ = gc.Suite(&ManifoldSuite{})
    46  
    47  func (s *ManifoldSuite) SetUpTest(c *gc.C) {
    48  	s.IsolationSuite.SetUpTest(c)
    49  
    50  	s.state = stubStateTracker{}
    51  	s.mux = &apiserverhttp.Mux{}
    52  	s.hub = pubsub.NewStructuredHub(nil)
    53  	s.clock = testclock.NewClock(time.Now())
    54  	s.prometheusRegisterer = stubPrometheusRegisterer{}
    55  	s.certWatcher = stubCertWatcher{}
    56  	s.tlsConfig = &tls.Config{}
    57  	s.controllerConfig = controller.Config(map[string]interface{}{
    58  		"api-port":            1024,
    59  		"controller-api-port": 2048,
    60  		"api-port-open-delay": "5s",
    61  	})
    62  	s.stub.ResetCalls()
    63  
    64  	s.context = s.newContext(nil)
    65  	s.config = httpserver.ManifoldConfig{
    66  		AgentName:            "machine-42",
    67  		CertWatcherName:      "cert-watcher",
    68  		HubName:              "hub",
    69  		StateName:            "state",
    70  		MuxName:              "mux",
    71  		APIServerName:        "api-server",
    72  		RaftTransportName:    "raft-transport",
    73  		Clock:                s.clock,
    74  		PrometheusRegisterer: &s.prometheusRegisterer,
    75  		MuxShutdownWait:      1 * time.Minute,
    76  		LogDir:               "log-dir",
    77  		GetControllerConfig:  s.getControllerConfig,
    78  		NewTLSConfig:         s.newTLSConfig,
    79  		NewWorker:            s.newWorker,
    80  	}
    81  	s.manifold = httpserver.Manifold(s.config)
    82  }
    83  
    84  func (s *ManifoldSuite) newContext(overlay map[string]interface{}) dependency.Context {
    85  	resources := map[string]interface{}{
    86  		"cert-watcher":   s.certWatcher.get,
    87  		"state":          &s.state,
    88  		"hub":            s.hub,
    89  		"mux":            s.mux,
    90  		"raft-transport": nil,
    91  		"api-server":     nil,
    92  	}
    93  	for k, v := range overlay {
    94  		resources[k] = v
    95  	}
    96  	return dt.StubContext(nil, resources)
    97  }
    98  
    99  func (s *ManifoldSuite) getControllerConfig(st *state.State) (controller.Config, error) {
   100  	s.stub.MethodCall(s, "GetControllerConfig", st)
   101  	if err := s.stub.NextErr(); err != nil {
   102  		return nil, err
   103  	}
   104  	return s.controllerConfig, nil
   105  }
   106  
   107  func (s *ManifoldSuite) newTLSConfig(
   108  	st *state.State,
   109  	getCertificate func() *tls.Certificate,
   110  ) (*tls.Config, error) {
   111  	s.stub.MethodCall(s, "NewTLSConfig", st)
   112  	if err := s.stub.NextErr(); err != nil {
   113  		return nil, err
   114  	}
   115  	return s.tlsConfig, nil
   116  }
   117  
   118  func (s *ManifoldSuite) newWorker(config httpserver.Config) (worker.Worker, error) {
   119  	s.stub.MethodCall(s, "NewWorker", config)
   120  	if err := s.stub.NextErr(); err != nil {
   121  		return nil, err
   122  	}
   123  	return worker.NewRunner(worker.RunnerParams{}), nil
   124  }
   125  
   126  var expectedInputs = []string{
   127  	"cert-watcher",
   128  	"state",
   129  	"mux",
   130  	"hub",
   131  	"raft-transport",
   132  	"api-server",
   133  }
   134  
   135  func (s *ManifoldSuite) TestInputs(c *gc.C) {
   136  	c.Assert(s.manifold.Inputs, jc.SameContents, expectedInputs)
   137  }
   138  
   139  func (s *ManifoldSuite) TestMissingInputs(c *gc.C) {
   140  	for _, input := range expectedInputs {
   141  		context := s.newContext(map[string]interface{}{
   142  			input: dependency.ErrMissing,
   143  		})
   144  		_, err := s.manifold.Start(context)
   145  		c.Assert(errors.Cause(err), gc.Equals, dependency.ErrMissing)
   146  	}
   147  }
   148  
   149  func (s *ManifoldSuite) TestStart(c *gc.C) {
   150  	w := s.startWorkerClean(c)
   151  	workertest.CleanKill(c, w)
   152  
   153  	s.stub.CheckCallNames(c, "NewTLSConfig", "GetControllerConfig", "NewWorker")
   154  	newWorkerArgs := s.stub.Calls()[2].Args
   155  	c.Assert(newWorkerArgs, gc.HasLen, 1)
   156  	c.Assert(newWorkerArgs[0], gc.FitsTypeOf, httpserver.Config{})
   157  	config := newWorkerArgs[0].(httpserver.Config)
   158  
   159  	c.Assert(config, jc.DeepEquals, httpserver.Config{
   160  		AgentName:            "machine-42",
   161  		Clock:                s.clock,
   162  		PrometheusRegisterer: &s.prometheusRegisterer,
   163  		Hub:                  s.hub,
   164  		TLSConfig:            s.tlsConfig,
   165  		Mux:                  s.mux,
   166  		APIPort:              1024,
   167  		APIPortOpenDelay:     5 * time.Second,
   168  		ControllerAPIPort:    2048,
   169  		MuxShutdownWait:      1 * time.Minute,
   170  		LogDir:               "log-dir",
   171  	})
   172  }
   173  
   174  func (s *ManifoldSuite) TestValidate(c *gc.C) {
   175  	type test struct {
   176  		f      func(*httpserver.ManifoldConfig)
   177  		expect string
   178  	}
   179  	tests := []test{{
   180  		func(cfg *httpserver.ManifoldConfig) { cfg.AgentName = "" },
   181  		"empty AgentName not valid",
   182  	}, {
   183  		func(cfg *httpserver.ManifoldConfig) { cfg.CertWatcherName = "" },
   184  		"empty CertWatcherName not valid",
   185  	}, {
   186  		func(cfg *httpserver.ManifoldConfig) { cfg.StateName = "" },
   187  		"empty StateName not valid",
   188  	}, {
   189  		func(cfg *httpserver.ManifoldConfig) { cfg.MuxName = "" },
   190  		"empty MuxName not valid",
   191  	}, {
   192  		func(cfg *httpserver.ManifoldConfig) { cfg.MuxShutdownWait = 0 },
   193  		"MuxShutdownWait 0s not valid",
   194  	}, {
   195  		func(cfg *httpserver.ManifoldConfig) { cfg.LogDir = "" },
   196  		"empty LogDir not valid",
   197  	}, {
   198  		func(cfg *httpserver.ManifoldConfig) { cfg.RaftTransportName = "" },
   199  		"empty RaftTransportName not valid",
   200  	}, {
   201  		func(cfg *httpserver.ManifoldConfig) { cfg.APIServerName = "" },
   202  		"empty APIServerName not valid",
   203  	}, {
   204  		func(cfg *httpserver.ManifoldConfig) { cfg.PrometheusRegisterer = nil },
   205  		"nil PrometheusRegisterer not valid",
   206  	}, {
   207  		func(cfg *httpserver.ManifoldConfig) { cfg.GetControllerConfig = nil },
   208  		"nil GetControllerConfig not valid",
   209  	}, {
   210  		func(cfg *httpserver.ManifoldConfig) { cfg.NewTLSConfig = nil },
   211  		"nil NewTLSConfig not valid",
   212  	}, {
   213  		func(cfg *httpserver.ManifoldConfig) { cfg.NewWorker = nil },
   214  		"nil NewWorker not valid",
   215  	}}
   216  	for i, test := range tests {
   217  		c.Logf("test #%d (%s)", i, test.expect)
   218  		config := s.config
   219  		test.f(&config)
   220  		manifold := httpserver.Manifold(config)
   221  		w, err := manifold.Start(s.context)
   222  		workertest.CheckNilOrKill(c, w)
   223  		c.Check(err, gc.ErrorMatches, test.expect)
   224  	}
   225  }
   226  
   227  func (s *ManifoldSuite) TestStopWorkerClosesState(c *gc.C) {
   228  	w := s.startWorkerClean(c)
   229  	defer workertest.CleanKill(c, w)
   230  
   231  	s.state.CheckCallNames(c, "Use")
   232  
   233  	workertest.CleanKill(c, w)
   234  	s.state.CheckCallNames(c, "Use", "Done")
   235  }
   236  
   237  func (s *ManifoldSuite) startWorkerClean(c *gc.C) worker.Worker {
   238  	w, err := s.manifold.Start(s.context)
   239  	c.Assert(err, jc.ErrorIsNil)
   240  	workertest.CheckAlive(c, w)
   241  	return w
   242  }