github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/addresser/addresser_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package addresser_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  
    12  	"github.com/juju/juju/apiserver/addresser"
    13  	"github.com/juju/juju/apiserver/common"
    14  	"github.com/juju/juju/apiserver/params"
    15  	apiservertesting "github.com/juju/juju/apiserver/testing"
    16  	"github.com/juju/juju/cmd/modelcmd"
    17  	"github.com/juju/juju/environs"
    18  	"github.com/juju/juju/environs/config"
    19  	"github.com/juju/juju/feature"
    20  	"github.com/juju/juju/instance"
    21  	"github.com/juju/juju/jujuclient/jujuclienttesting"
    22  	"github.com/juju/juju/network"
    23  	"github.com/juju/juju/provider/dummy"
    24  	"github.com/juju/juju/state"
    25  	statetesting "github.com/juju/juju/state/testing"
    26  	coretesting "github.com/juju/juju/testing"
    27  )
    28  
    29  type AddresserSuite struct {
    30  	coretesting.BaseSuite
    31  
    32  	st         *mockState
    33  	api        *addresser.AddresserAPI
    34  	authoriser apiservertesting.FakeAuthorizer
    35  	resources  *common.Resources
    36  }
    37  
    38  var _ = gc.Suite(&AddresserSuite{})
    39  
    40  func (s *AddresserSuite) SetUpSuite(c *gc.C) {
    41  	s.BaseSuite.SetUpSuite(c)
    42  	environs.RegisterProvider("mock", mockEnvironProvider{})
    43  }
    44  
    45  func (s *AddresserSuite) SetUpTest(c *gc.C) {
    46  	s.BaseSuite.SetUpTest(c)
    47  	s.SetFeatureFlags(feature.AddressAllocation)
    48  
    49  	s.authoriser = apiservertesting.FakeAuthorizer{
    50  		EnvironManager: true,
    51  	}
    52  	s.resources = common.NewResources()
    53  	s.AddCleanup(func(*gc.C) { s.resources.StopAll() })
    54  
    55  	s.st = newMockState()
    56  	addresser.PatchState(s, s.st)
    57  
    58  	var err error
    59  	s.api, err = addresser.NewAddresserAPI(nil, s.resources, s.authoriser)
    60  	c.Assert(err, jc.ErrorIsNil)
    61  	s.AddCleanup(dummy.Reset)
    62  }
    63  
    64  func (s *AddresserSuite) TestCanDeallocateAddressesEnabled(c *gc.C) {
    65  	config := testingEnvConfig(c)
    66  	s.st.setConfig(c, config)
    67  
    68  	result := s.api.CanDeallocateAddresses()
    69  	c.Assert(result, jc.DeepEquals, params.BoolResult{
    70  		Error:  nil,
    71  		Result: true,
    72  	})
    73  }
    74  
    75  func (s *AddresserSuite) TestCanDeallocateAddressesDisabled(c *gc.C) {
    76  	config := testingEnvConfig(c)
    77  	s.st.setConfig(c, config)
    78  	s.SetFeatureFlags()
    79  
    80  	result := s.api.CanDeallocateAddresses()
    81  	c.Assert(result, jc.DeepEquals, params.BoolResult{
    82  		Error:  nil,
    83  		Result: false,
    84  	})
    85  }
    86  
    87  func (s *AddresserSuite) TestCanDeallocateAddressesConfigGetFailure(c *gc.C) {
    88  	config := testingEnvConfig(c)
    89  	s.st.setConfig(c, config)
    90  
    91  	s.st.stub.SetErrors(errors.New("ouch"))
    92  
    93  	result := s.api.CanDeallocateAddresses()
    94  	c.Assert(result.Error, gc.ErrorMatches, "getting model config: ouch")
    95  	c.Assert(result.Result, jc.IsFalse)
    96  }
    97  
    98  func (s *AddresserSuite) TestCanDeallocateAddressesEnvironmentNewFailure(c *gc.C) {
    99  	config := nonexTestingEnvConfig(c)
   100  	s.st.setConfig(c, config)
   101  
   102  	result := s.api.CanDeallocateAddresses()
   103  	c.Assert(result.Error, gc.ErrorMatches, `validating model config: no registered provider for "nonex"`)
   104  	c.Assert(result.Result, jc.IsFalse)
   105  }
   106  
   107  func (s *AddresserSuite) TestCanDeallocateAddressesNotSupportedFailure(c *gc.C) {
   108  	config := mockTestingEnvConfig(c)
   109  	s.st.setConfig(c, config)
   110  
   111  	result := s.api.CanDeallocateAddresses()
   112  	c.Assert(result, jc.DeepEquals, params.BoolResult{
   113  		Error:  nil,
   114  		Result: false,
   115  	})
   116  }
   117  
   118  func (s *AddresserSuite) TestCleanupIPAddressesSuccess(c *gc.C) {
   119  	config := testingEnvConfig(c)
   120  	s.st.setConfig(c, config)
   121  
   122  	dead, err := s.st.DeadIPAddresses()
   123  	c.Assert(err, jc.ErrorIsNil)
   124  	c.Assert(dead, gc.HasLen, 2)
   125  
   126  	apiErr := s.api.CleanupIPAddresses()
   127  	c.Assert(apiErr, jc.DeepEquals, params.ErrorResult{})
   128  
   129  	dead, err = s.st.DeadIPAddresses()
   130  	c.Assert(err, jc.ErrorIsNil)
   131  	c.Assert(dead, gc.HasLen, 0)
   132  }
   133  
   134  func (s *AddresserSuite) TestReleaseAddress(c *gc.C) {
   135  	config := testingEnvConfig(c)
   136  	s.st.setConfig(c, config)
   137  
   138  	// Cleanup initial dead IP addresses.
   139  	dead, err := s.st.DeadIPAddresses()
   140  	c.Assert(err, jc.ErrorIsNil)
   141  	c.Assert(dead, gc.HasLen, 2)
   142  
   143  	apiErr := s.api.CleanupIPAddresses()
   144  	c.Assert(apiErr, jc.DeepEquals, params.ErrorResult{})
   145  
   146  	dead, err = s.st.DeadIPAddresses()
   147  	c.Assert(err, jc.ErrorIsNil)
   148  	c.Assert(dead, gc.HasLen, 0)
   149  
   150  	// Prepare tests.
   151  	called := 0
   152  	s.PatchValue(addresser.NetEnvReleaseAddress, func(
   153  		env environs.NetworkingEnviron,
   154  		instId instance.Id,
   155  		subnetId network.Id,
   156  		addr network.Address,
   157  		macAddress, hostname string,
   158  	) error {
   159  		called++
   160  		c.Assert(instId, gc.Equals, instance.Id("a3"))
   161  		c.Assert(subnetId, gc.Equals, network.Id("a"))
   162  		c.Assert(addr, gc.Equals, network.NewAddress("0.1.2.3"))
   163  		c.Assert(macAddress, gc.Equals, "fff3")
   164  		c.Assert(hostname, gc.Equals, "")
   165  		return nil
   166  	})
   167  
   168  	// Set address 0.1.2.3 to dead.
   169  	s.st.setDead(c, "0.1.2.3")
   170  
   171  	dead, err = s.st.DeadIPAddresses()
   172  	c.Assert(err, jc.ErrorIsNil)
   173  	c.Assert(dead, gc.HasLen, 1)
   174  
   175  	apiErr = s.api.CleanupIPAddresses()
   176  	c.Assert(apiErr, jc.DeepEquals, params.ErrorResult{})
   177  	c.Assert(called, gc.Equals, 1)
   178  
   179  	dead, err = s.st.DeadIPAddresses()
   180  	c.Assert(err, jc.ErrorIsNil)
   181  	c.Assert(dead, gc.HasLen, 0)
   182  }
   183  
   184  func (s *AddresserSuite) TestCleanupIPAddressesConfigGetFailure(c *gc.C) {
   185  	config := testingEnvConfig(c)
   186  	s.st.setConfig(c, config)
   187  
   188  	dead, err := s.st.DeadIPAddresses()
   189  	c.Assert(err, jc.ErrorIsNil)
   190  	c.Assert(dead, gc.HasLen, 2)
   191  
   192  	s.st.stub.SetErrors(errors.New("ouch"))
   193  
   194  	// First action is getting the environment configuration,
   195  	// so the injected error is returned here.
   196  	apiErr := s.api.CleanupIPAddresses()
   197  	c.Assert(apiErr.Error, gc.ErrorMatches, "getting model config: ouch")
   198  
   199  	// Still has two dead addresses.
   200  	dead, err = s.st.DeadIPAddresses()
   201  	c.Assert(err, jc.ErrorIsNil)
   202  	c.Assert(dead, gc.HasLen, 2)
   203  }
   204  
   205  func (s *AddresserSuite) TestCleanupIPAddressesEnvironmentNewFailure(c *gc.C) {
   206  	config := nonexTestingEnvConfig(c)
   207  	s.st.setConfig(c, config)
   208  
   209  	dead, err := s.st.DeadIPAddresses()
   210  	c.Assert(err, jc.ErrorIsNil)
   211  	c.Assert(dead, gc.HasLen, 2)
   212  
   213  	// Validation of configuration fails due to illegal provider.
   214  	apiErr := s.api.CleanupIPAddresses()
   215  	c.Assert(apiErr.Error, gc.ErrorMatches, `validating model config: no registered provider for "nonex"`)
   216  
   217  	// Still has two dead addresses.
   218  	dead, err = s.st.DeadIPAddresses()
   219  	c.Assert(err, jc.ErrorIsNil)
   220  	c.Assert(dead, gc.HasLen, 2)
   221  }
   222  
   223  func (s *AddresserSuite) TestCleanupIPAddressesNotSupportedFailure(c *gc.C) {
   224  	config := mockTestingEnvConfig(c)
   225  	s.st.setConfig(c, config)
   226  
   227  	dead, err := s.st.DeadIPAddresses()
   228  	c.Assert(err, jc.ErrorIsNil)
   229  	c.Assert(dead, gc.HasLen, 2)
   230  
   231  	// The tideland environment does not support networking.
   232  	apiErr := s.api.CleanupIPAddresses()
   233  	c.Assert(apiErr.Error, gc.ErrorMatches, "IP address deallocation not supported")
   234  
   235  	// Still has two dead addresses.
   236  	dead, err = s.st.DeadIPAddresses()
   237  	c.Assert(err, jc.ErrorIsNil)
   238  	c.Assert(dead, gc.HasLen, 2)
   239  }
   240  
   241  func (s *AddresserSuite) TestWatchIPAddresses(c *gc.C) {
   242  	c.Assert(s.resources.Count(), gc.Equals, 0)
   243  
   244  	s.st.addIPAddressWatcher("0.1.2.3", "0.1.2.4", "0.1.2.7")
   245  
   246  	result, err := s.api.WatchIPAddresses()
   247  	c.Assert(err, jc.ErrorIsNil)
   248  	c.Assert(result, gc.DeepEquals, params.EntitiesWatchResult{
   249  		EntitiesWatcherId: "1",
   250  		Changes: []string{
   251  			"ipaddress-00000000-1111-2222-3333-0123456789ab",
   252  			"ipaddress-00000000-1111-2222-4444-0123456789ab",
   253  			"ipaddress-00000000-1111-2222-7777-0123456789ab",
   254  		},
   255  		Error: nil,
   256  	})
   257  
   258  	// Verify the resource was registered and stop when done.
   259  	c.Assert(s.resources.Count(), gc.Equals, 1)
   260  	resource := s.resources.Get("1")
   261  	defer statetesting.AssertStop(c, resource)
   262  
   263  	// Check that the Watch has consumed the initial event ("returned" in
   264  	// the Watch call)
   265  	wc := statetesting.NewStringsWatcherC(c, s.st, resource.(state.StringsWatcher))
   266  	wc.AssertNoChange()
   267  }
   268  
   269  // testingEnvConfig prepares an environment configuration using
   270  // the dummy provider.
   271  func testingEnvConfig(c *gc.C) *config.Config {
   272  	env, err := environs.Prepare(
   273  		modelcmd.BootstrapContext(coretesting.Context(c)),
   274  		jujuclienttesting.NewMemStore(),
   275  		environs.PrepareParams{
   276  			ControllerName: "dummycontroller",
   277  			BaseConfig:     dummy.SampleConfig(),
   278  			CloudName:      "dummy",
   279  		},
   280  	)
   281  	c.Assert(err, jc.ErrorIsNil)
   282  	return env.Config()
   283  }
   284  
   285  // nonexTestingEnvConfig prepares an environment configuration using
   286  // a non-existent provider.
   287  func nonexTestingEnvConfig(c *gc.C) *config.Config {
   288  	attrs := dummy.SampleConfig().Merge(coretesting.Attrs{
   289  		"type": "nonex",
   290  	})
   291  	cfg, err := config.New(config.NoDefaults, attrs)
   292  	c.Assert(err, jc.ErrorIsNil)
   293  	return cfg
   294  }
   295  
   296  // mockTestingEnvConfig prepares an environment configuration using
   297  // the mock provider which does not support networking.
   298  func mockTestingEnvConfig(c *gc.C) *config.Config {
   299  	env, err := environs.Prepare(
   300  		modelcmd.BootstrapContext(coretesting.Context(c)),
   301  		jujuclienttesting.NewMemStore(),
   302  		environs.PrepareParams{
   303  			ControllerName: "dummycontroller",
   304  			BaseConfig:     mockConfig(),
   305  			CloudName:      "dummy",
   306  		},
   307  	)
   308  	c.Assert(err, jc.ErrorIsNil)
   309  	return env.Config()
   310  }