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 }