github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/api/controller/legacy_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package controller_test
     5  
     6  import (
     7  	"fmt"
     8  	"net"
     9  	"time"
    10  
    11  	jc "github.com/juju/testing/checkers"
    12  	"github.com/juju/utils/clock"
    13  	gc "gopkg.in/check.v1"
    14  	"gopkg.in/juju/names.v2"
    15  
    16  	"github.com/juju/juju/api"
    17  	"github.com/juju/juju/api/base"
    18  	"github.com/juju/juju/api/controller"
    19  	"github.com/juju/juju/apiserver"
    20  	commontesting "github.com/juju/juju/apiserver/common/testing"
    21  	"github.com/juju/juju/apiserver/observer"
    22  	"github.com/juju/juju/apiserver/observer/fakeobserver"
    23  	"github.com/juju/juju/apiserver/params"
    24  	jujutesting "github.com/juju/juju/juju/testing"
    25  	"github.com/juju/juju/permission"
    26  	"github.com/juju/juju/state"
    27  	"github.com/juju/juju/state/multiwatcher"
    28  	"github.com/juju/juju/testing"
    29  	"github.com/juju/juju/testing/factory"
    30  )
    31  
    32  // legacySuite has the tests for the controller client-side facade
    33  // which use JujuConnSuite. The plan is to gradually move these tests
    34  // to Suite in controller_test.go.
    35  type legacySuite struct {
    36  	jujutesting.JujuConnSuite
    37  	commontesting.BlockHelper
    38  }
    39  
    40  var _ = gc.Suite(&legacySuite{})
    41  
    42  func (s *legacySuite) OpenAPI(c *gc.C) *controller.Client {
    43  	return controller.NewClient(s.OpenControllerAPI(c))
    44  }
    45  
    46  func (s *legacySuite) TestAllModels(c *gc.C) {
    47  	owner := names.NewUserTag("user@remote")
    48  	s.Factory.MakeModel(c, &factory.ModelParams{
    49  		Name: "first", Owner: owner}).Close()
    50  	s.Factory.MakeModel(c, &factory.ModelParams{
    51  		Name: "second", Owner: owner}).Close()
    52  
    53  	sysManager := s.OpenAPI(c)
    54  	defer sysManager.Close()
    55  	envs, err := sysManager.AllModels()
    56  	c.Assert(err, jc.ErrorIsNil)
    57  	c.Assert(envs, gc.HasLen, 3)
    58  
    59  	var obtained []string
    60  	for _, env := range envs {
    61  		obtained = append(obtained, fmt.Sprintf("%s/%s", env.Owner, env.Name))
    62  	}
    63  	expected := []string{
    64  		"admin@local/controller",
    65  		"user@remote/first",
    66  		"user@remote/second",
    67  	}
    68  	c.Assert(obtained, jc.SameContents, expected)
    69  }
    70  
    71  func (s *legacySuite) TestModelConfig(c *gc.C) {
    72  	sysManager := s.OpenAPI(c)
    73  	defer sysManager.Close()
    74  	cfg, err := sysManager.ModelConfig()
    75  	c.Assert(err, jc.ErrorIsNil)
    76  	c.Assert(cfg["name"], gc.Equals, "controller")
    77  }
    78  
    79  func (s *legacySuite) TestControllerConfig(c *gc.C) {
    80  	sysManager := s.OpenAPI(c)
    81  	defer sysManager.Close()
    82  	cfg, err := sysManager.ControllerConfig()
    83  	c.Assert(err, jc.ErrorIsNil)
    84  	cfgFromDB, err := s.State.ControllerConfig()
    85  	c.Assert(err, jc.ErrorIsNil)
    86  	c.Assert(cfg["controller-uuid"], gc.Equals, cfgFromDB.ControllerUUID())
    87  	c.Assert(int(cfg["state-port"].(float64)), gc.Equals, cfgFromDB.StatePort())
    88  	c.Assert(int(cfg["api-port"].(float64)), gc.Equals, cfgFromDB.APIPort())
    89  }
    90  
    91  func (s *legacySuite) TestDestroyController(c *gc.C) {
    92  	st := s.Factory.MakeModel(c, &factory.ModelParams{Name: "foo"})
    93  	factory.NewFactory(st).MakeMachine(c, nil) // make it non-empty
    94  	st.Close()
    95  
    96  	sysManager := s.OpenAPI(c)
    97  	defer sysManager.Close()
    98  	err := sysManager.DestroyController(false)
    99  	c.Assert(err, gc.ErrorMatches, `failed to destroy model: hosting 1 other models \(controller has hosted models\)`)
   100  }
   101  
   102  func (s *legacySuite) TestListBlockedModels(c *gc.C) {
   103  	err := s.State.SwitchBlockOn(state.ChangeBlock, "change block for controller")
   104  	err = s.State.SwitchBlockOn(state.DestroyBlock, "destroy block for controller")
   105  	c.Assert(err, jc.ErrorIsNil)
   106  
   107  	sysManager := s.OpenAPI(c)
   108  	defer sysManager.Close()
   109  	results, err := sysManager.ListBlockedModels()
   110  	c.Assert(err, jc.ErrorIsNil)
   111  	c.Assert(results, jc.DeepEquals, []params.ModelBlockInfo{
   112  		{
   113  			Name:     "controller",
   114  			UUID:     s.State.ModelUUID(),
   115  			OwnerTag: s.AdminUserTag(c).String(),
   116  			Blocks: []string{
   117  				"BlockChange",
   118  				"BlockDestroy",
   119  			},
   120  		},
   121  	})
   122  }
   123  
   124  func (s *legacySuite) TestRemoveBlocks(c *gc.C) {
   125  	s.State.SwitchBlockOn(state.DestroyBlock, "TestBlockDestroyModel")
   126  	s.State.SwitchBlockOn(state.ChangeBlock, "TestChangeBlock")
   127  
   128  	sysManager := s.OpenAPI(c)
   129  	defer sysManager.Close()
   130  	err := sysManager.RemoveBlocks()
   131  	c.Assert(err, jc.ErrorIsNil)
   132  
   133  	blocks, err := s.State.AllBlocksForController()
   134  	c.Assert(err, jc.ErrorIsNil)
   135  	c.Assert(blocks, gc.HasLen, 0)
   136  }
   137  
   138  func (s *legacySuite) TestWatchAllModels(c *gc.C) {
   139  	// The WatchAllModels infrastructure is comprehensively tested
   140  	// else. This test just ensure that the API calls work end-to-end.
   141  	sysManager := s.OpenAPI(c)
   142  	defer sysManager.Close()
   143  
   144  	w, err := sysManager.WatchAllModels()
   145  	c.Assert(err, jc.ErrorIsNil)
   146  	defer func() {
   147  		err := w.Stop()
   148  		c.Assert(err, jc.ErrorIsNil)
   149  	}()
   150  
   151  	deltasC := make(chan []multiwatcher.Delta)
   152  	go func() {
   153  		deltas, err := w.Next()
   154  		c.Assert(err, jc.ErrorIsNil)
   155  		deltasC <- deltas
   156  	}()
   157  
   158  	select {
   159  	case deltas := <-deltasC:
   160  		c.Assert(deltas, gc.HasLen, 1)
   161  		modelInfo := deltas[0].Entity.(*multiwatcher.ModelInfo)
   162  
   163  		env, err := s.State.Model()
   164  		c.Assert(err, jc.ErrorIsNil)
   165  
   166  		c.Assert(modelInfo.ModelUUID, gc.Equals, env.UUID())
   167  		c.Assert(modelInfo.Name, gc.Equals, env.Name())
   168  		c.Assert(modelInfo.Life, gc.Equals, multiwatcher.Life("alive"))
   169  		c.Assert(modelInfo.Owner, gc.Equals, env.Owner().Id())
   170  		c.Assert(modelInfo.ControllerUUID, gc.Equals, env.ControllerUUID())
   171  	case <-time.After(testing.LongWait):
   172  		c.Fatal("timed out")
   173  	}
   174  }
   175  
   176  func (s *legacySuite) TestAPIServerCanShutdownWithOutstandingNext(c *gc.C) {
   177  
   178  	lis, err := net.Listen("tcp", "localhost:0")
   179  	c.Assert(err, jc.ErrorIsNil)
   180  
   181  	srv, err := apiserver.NewServer(s.State, lis, apiserver.ServerConfig{
   182  		Clock:       clock.WallClock,
   183  		Cert:        testing.ServerCert,
   184  		Key:         testing.ServerKey,
   185  		Tag:         names.NewMachineTag("0"),
   186  		DataDir:     c.MkDir(),
   187  		LogDir:      c.MkDir(),
   188  		NewObserver: func() observer.Observer { return &fakeobserver.Instance{} },
   189  		AutocertURL: "https://0.1.2.3/no-autocert-here",
   190  	})
   191  	c.Assert(err, gc.IsNil)
   192  
   193  	// Connect to the API server we've just started.
   194  	apiInfo := s.APIInfo(c)
   195  	apiInfo.Addrs = []string{lis.Addr().String()}
   196  	apiInfo.ModelTag = names.ModelTag{}
   197  	apiState, err := api.Open(apiInfo, api.DialOpts{})
   198  	sysManager := controller.NewClient(apiState)
   199  	defer sysManager.Close()
   200  
   201  	w, err := sysManager.WatchAllModels()
   202  	c.Assert(err, jc.ErrorIsNil)
   203  	defer w.Stop()
   204  
   205  	deltasC := make(chan struct{}, 2)
   206  	go func() {
   207  		defer close(deltasC)
   208  		for {
   209  			_, err := w.Next()
   210  			if err != nil {
   211  				return
   212  			}
   213  			deltasC <- struct{}{}
   214  		}
   215  	}()
   216  	// Read the first event.
   217  	select {
   218  	case <-deltasC:
   219  	case <-time.After(testing.LongWait):
   220  		c.Fatal("timed out")
   221  	}
   222  	// Wait a little while for the Next call to actually arrive.
   223  	time.Sleep(testing.ShortWait)
   224  
   225  	// We should be able to close the server instance
   226  	// even when there's an outstanding Next call.
   227  	srvStopped := make(chan struct{})
   228  	go func() {
   229  		srv.Stop()
   230  		close(srvStopped)
   231  	}()
   232  
   233  	select {
   234  	case <-srvStopped:
   235  	case <-time.After(testing.LongWait):
   236  		c.Fatal("timed out waiting for server to stop")
   237  	}
   238  
   239  	// Check that the Next call has returned too.
   240  	select {
   241  	case _, ok := <-deltasC:
   242  		if ok {
   243  			c.Fatalf("got unexpected event from deltasC")
   244  		}
   245  	case <-time.After(testing.LongWait):
   246  		c.Fatal("timed out")
   247  	}
   248  }
   249  
   250  func (s *legacySuite) TestModelStatus(c *gc.C) {
   251  	sysManager := s.OpenAPI(c)
   252  	defer sysManager.Close()
   253  	s.Factory.MakeMachine(c, nil)
   254  	modelTag := s.State.ModelTag()
   255  	results, err := sysManager.ModelStatus(modelTag)
   256  	c.Assert(err, jc.ErrorIsNil)
   257  	c.Assert(results, jc.DeepEquals, []base.ModelStatus{{
   258  		UUID:               modelTag.Id(),
   259  		TotalMachineCount:  1,
   260  		HostedMachineCount: 1,
   261  		ServiceCount:       0,
   262  		Owner:              "admin@local",
   263  		Life:               string(params.Alive),
   264  		Machines:           []base.Machine{{Id: "0", InstanceId: "id-2", Status: "pending"}},
   265  	}})
   266  }
   267  
   268  func (s *legacySuite) TestGetControllerAccess(c *gc.C) {
   269  	controller := s.OpenAPI(c)
   270  	defer controller.Close()
   271  	err := controller.GrantController("fred@external", "addmodel")
   272  	c.Assert(err, jc.ErrorIsNil)
   273  	access, err := controller.GetControllerAccess("fred@external")
   274  	c.Assert(err, jc.ErrorIsNil)
   275  	c.Assert(access, gc.Equals, permission.Access("addmodel"))
   276  }