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