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 }