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