github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/azure/instance_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package azure_test 5 6 import ( 7 "net/http" 8 "path" 9 10 "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-08-01/network" 11 "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-05-01/resources" 12 "github.com/Azure/go-autorest/autorest/mocks" 13 "github.com/Azure/go-autorest/autorest/to" 14 jc "github.com/juju/testing/checkers" 15 gc "gopkg.in/check.v1" 16 17 "github.com/juju/juju/core/instance" 18 "github.com/juju/juju/core/status" 19 "github.com/juju/juju/environs" 20 "github.com/juju/juju/environs/context" 21 "github.com/juju/juju/environs/instances" 22 jujunetwork "github.com/juju/juju/network" 23 "github.com/juju/juju/provider/azure" 24 "github.com/juju/juju/provider/azure/internal/azuretesting" 25 "github.com/juju/juju/testing" 26 ) 27 28 type instanceSuite struct { 29 testing.BaseSuite 30 31 provider environs.EnvironProvider 32 requests []*http.Request 33 sender azuretesting.Senders 34 env environs.Environ 35 deployments []resources.DeploymentExtended 36 networkInterfaces []network.Interface 37 publicIPAddresses []network.PublicIPAddress 38 39 callCtx *context.CloudCallContext 40 invalidteCredential bool 41 } 42 43 var _ = gc.Suite(&instanceSuite{}) 44 45 func (s *instanceSuite) SetUpTest(c *gc.C) { 46 s.BaseSuite.SetUpTest(c) 47 s.provider = newProvider(c, azure.ProviderConfig{ 48 Sender: &s.sender, 49 RequestInspector: azuretesting.RequestRecorder(&s.requests), 50 RandomWindowsAdminPassword: func() string { return "sorandom" }, 51 }) 52 s.env = openEnviron(c, s.provider, &s.sender) 53 azure.SetRetries(s.env) 54 s.sender = nil 55 s.requests = nil 56 s.networkInterfaces = []network.Interface{ 57 makeNetworkInterface("nic-0", "machine-0"), 58 } 59 s.publicIPAddresses = nil 60 s.deployments = []resources.DeploymentExtended{ 61 makeDeployment("machine-0"), 62 makeDeployment("machine-1"), 63 } 64 s.callCtx = &context.CloudCallContext{ 65 InvalidateCredentialFunc: func(string) error { 66 s.invalidteCredential = true 67 return nil 68 }, 69 } 70 } 71 72 func makeDeployment(name string) resources.DeploymentExtended { 73 dependsOn := []resources.BasicDependency{{ 74 ResourceType: to.StringPtr("Microsoft.Compute/availabilitySets"), 75 ResourceName: to.StringPtr("mysql"), 76 }} 77 dependencies := []resources.Dependency{{ 78 ResourceType: to.StringPtr("Microsoft.Compute/virtualMachines"), 79 DependsOn: &dependsOn, 80 }} 81 return resources.DeploymentExtended{ 82 Name: to.StringPtr(name), 83 Properties: &resources.DeploymentPropertiesExtended{ 84 ProvisioningState: to.StringPtr("Succeeded"), 85 Dependencies: &dependencies, 86 }, 87 } 88 } 89 90 func makeNetworkInterface(nicName, vmName string, ipConfigurations ...network.InterfaceIPConfiguration) network.Interface { 91 tags := map[string]*string{"juju-machine-name": &vmName} 92 return network.Interface{ 93 Name: to.StringPtr(nicName), 94 Tags: tags, 95 InterfacePropertiesFormat: &network.InterfacePropertiesFormat{ 96 IPConfigurations: &ipConfigurations, 97 }, 98 } 99 } 100 101 func makeIPConfiguration(privateIPAddress string) network.InterfaceIPConfiguration { 102 ipConfiguration := network.InterfaceIPConfiguration{ 103 InterfaceIPConfigurationPropertiesFormat: &network.InterfaceIPConfigurationPropertiesFormat{}, 104 } 105 if privateIPAddress != "" { 106 ipConfiguration.PrivateIPAddress = to.StringPtr(privateIPAddress) 107 } 108 return ipConfiguration 109 } 110 111 func makePublicIPAddress(pipName, vmName, ipAddress string) network.PublicIPAddress { 112 tags := map[string]*string{"juju-machine-name": &vmName} 113 pip := network.PublicIPAddress{ 114 Name: to.StringPtr(pipName), 115 Tags: tags, 116 PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{}, 117 } 118 if ipAddress != "" { 119 pip.IPAddress = to.StringPtr(ipAddress) 120 } 121 return pip 122 } 123 124 func makeSecurityGroup(rules ...network.SecurityRule) network.SecurityGroup { 125 return network.SecurityGroup{ 126 SecurityGroupPropertiesFormat: &network.SecurityGroupPropertiesFormat{ 127 SecurityRules: &rules, 128 }, 129 } 130 } 131 132 func makeSecurityRule(name, ipAddress, ports string) network.SecurityRule { 133 return network.SecurityRule{ 134 Name: to.StringPtr(name), 135 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 136 Protocol: network.SecurityRuleProtocolTCP, 137 DestinationAddressPrefix: to.StringPtr(ipAddress), 138 DestinationPortRange: to.StringPtr(ports), 139 Access: network.SecurityRuleAccessAllow, 140 Priority: to.Int32Ptr(200), 141 Direction: network.SecurityRuleDirectionInbound, 142 }, 143 } 144 } 145 146 func (s *instanceSuite) getInstance(c *gc.C) instances.Instance { 147 instances := s.getInstances(c, "machine-0") 148 c.Assert(instances, gc.HasLen, 1) 149 return instances[0] 150 } 151 152 func (s *instanceSuite) getInstances(c *gc.C, ids ...instance.Id) []instances.Instance { 153 s.sender = s.getInstancesSender() 154 instances, err := s.env.Instances(s.callCtx, ids) 155 c.Assert(err, jc.ErrorIsNil) 156 s.sender = azuretesting.Senders{} 157 s.requests = nil 158 return instances 159 } 160 161 func (s *instanceSuite) getInstancesSender() azuretesting.Senders { 162 deploymentsSender := azuretesting.NewSenderWithValue(&resources.DeploymentListResult{ 163 Value: &s.deployments, 164 }) 165 deploymentsSender.PathPattern = ".*/deployments" 166 nicsSender := azuretesting.NewSenderWithValue(&network.InterfaceListResult{ 167 Value: &s.networkInterfaces, 168 }) 169 nicsSender.PathPattern = ".*/networkInterfaces" 170 pipsSender := azuretesting.NewSenderWithValue(&network.PublicIPAddressListResult{ 171 Value: &s.publicIPAddresses, 172 }) 173 pipsSender.PathPattern = ".*/publicIPAddresses" 174 return azuretesting.Senders{deploymentsSender, nicsSender, pipsSender} 175 } 176 177 func networkSecurityGroupSender(rules []network.SecurityRule) *azuretesting.MockSender { 178 nsgSender := azuretesting.NewSenderWithValue(&network.SecurityGroup{ 179 SecurityGroupPropertiesFormat: &network.SecurityGroupPropertiesFormat{ 180 SecurityRules: &rules, 181 }, 182 }) 183 nsgSender.PathPattern = ".*/networkSecurityGroups/juju-internal-nsg" 184 return nsgSender 185 } 186 187 func (s *instanceSuite) TestInstanceStatus(c *gc.C) { 188 inst := s.getInstance(c) 189 assertInstanceStatus(c, inst.Status(s.callCtx), status.Running, "") 190 } 191 192 func (s *instanceSuite) TestInstanceStatusDeploymentFailed(c *gc.C) { 193 s.deployments[0].Properties.ProvisioningState = to.StringPtr("Failed") 194 inst := s.getInstance(c) 195 assertInstanceStatus(c, inst.Status(s.callCtx), status.ProvisioningError, "Failed") 196 } 197 198 func (s *instanceSuite) TestInstanceStatusDeploymentCanceled(c *gc.C) { 199 s.deployments[0].Properties.ProvisioningState = to.StringPtr("Canceled") 200 inst := s.getInstance(c) 201 assertInstanceStatus(c, inst.Status(s.callCtx), status.ProvisioningError, "Canceled") 202 } 203 204 func (s *instanceSuite) TestInstanceStatusNilProvisioningState(c *gc.C) { 205 s.deployments[0].Properties.ProvisioningState = nil 206 inst := s.getInstance(c) 207 assertInstanceStatus(c, inst.Status(s.callCtx), status.Allocating, "") 208 } 209 210 func assertInstanceStatus(c *gc.C, actual instance.Status, status status.Status, message string) { 211 c.Assert(actual, jc.DeepEquals, instance.Status{ 212 Status: status, 213 Message: message, 214 }) 215 } 216 217 func (s *instanceSuite) TestInstanceAddressesEmpty(c *gc.C) { 218 addresses, err := s.getInstance(c).Addresses(s.callCtx) 219 c.Assert(err, jc.ErrorIsNil) 220 c.Assert(addresses, gc.HasLen, 0) 221 } 222 223 func (s *instanceSuite) TestInstanceAddresses(c *gc.C) { 224 nic0IPConfigurations := []network.InterfaceIPConfiguration{ 225 makeIPConfiguration("10.0.0.4"), 226 makeIPConfiguration("10.0.0.5"), 227 } 228 nic1IPConfigurations := []network.InterfaceIPConfiguration{ 229 makeIPConfiguration(""), 230 } 231 s.networkInterfaces = []network.Interface{ 232 makeNetworkInterface("nic-0", "machine-0", nic0IPConfigurations...), 233 makeNetworkInterface("nic-1", "machine-0", nic1IPConfigurations...), 234 makeNetworkInterface("nic-2", "machine-0"), 235 // unrelated NIC 236 makeNetworkInterface("nic-3", "machine-1"), 237 } 238 s.publicIPAddresses = []network.PublicIPAddress{ 239 makePublicIPAddress("pip-0", "machine-0", "1.2.3.4"), 240 makePublicIPAddress("pip-1", "machine-0", "1.2.3.5"), 241 // unrelated PIP 242 makePublicIPAddress("pip-2", "machine-1", "1.2.3.6"), 243 } 244 addresses, err := s.getInstance(c).Addresses(s.callCtx) 245 c.Assert(err, jc.ErrorIsNil) 246 c.Assert(addresses, jc.DeepEquals, jujunetwork.NewAddresses( 247 "10.0.0.4", "10.0.0.5", "1.2.3.4", "1.2.3.5", 248 )) 249 } 250 251 func (s *instanceSuite) TestMultipleInstanceAddresses(c *gc.C) { 252 nic0IPConfiguration := makeIPConfiguration("10.0.0.4") 253 nic1IPConfiguration := makeIPConfiguration("10.0.0.5") 254 s.networkInterfaces = []network.Interface{ 255 makeNetworkInterface("nic-0", "machine-0", nic0IPConfiguration), 256 makeNetworkInterface("nic-1", "machine-1", nic1IPConfiguration), 257 } 258 s.publicIPAddresses = []network.PublicIPAddress{ 259 makePublicIPAddress("pip-0", "machine-0", "1.2.3.4"), 260 makePublicIPAddress("pip-1", "machine-1", "1.2.3.5"), 261 } 262 instances := s.getInstances(c, "machine-0", "machine-1") 263 c.Assert(instances, gc.HasLen, 2) 264 265 inst0Addresses, err := instances[0].Addresses(s.callCtx) 266 c.Assert(err, jc.ErrorIsNil) 267 c.Assert(inst0Addresses, jc.DeepEquals, jujunetwork.NewAddresses( 268 "10.0.0.4", "1.2.3.4", 269 )) 270 271 inst1Addresses, err := instances[1].Addresses(s.callCtx) 272 c.Assert(err, jc.ErrorIsNil) 273 c.Assert(inst1Addresses, jc.DeepEquals, jujunetwork.NewAddresses( 274 "10.0.0.5", "1.2.3.5", 275 )) 276 } 277 278 func (s *instanceSuite) TestIngressRulesEmpty(c *gc.C) { 279 inst := s.getInstance(c) 280 fwInst, ok := inst.(instances.InstanceFirewaller) 281 c.Assert(ok, gc.Equals, true) 282 nsgSender := networkSecurityGroupSender(nil) 283 s.sender = azuretesting.Senders{nsgSender} 284 rules, err := fwInst.IngressRules(s.callCtx, "0") 285 c.Assert(err, jc.ErrorIsNil) 286 c.Assert(rules, gc.HasLen, 0) 287 } 288 289 func (s *instanceSuite) TestIngressRules(c *gc.C) { 290 inst := s.getInstance(c) 291 nsgSender := networkSecurityGroupSender([]network.SecurityRule{{ 292 Name: to.StringPtr("machine-0-xyzzy"), 293 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 294 Protocol: network.SecurityRuleProtocolUDP, 295 DestinationPortRange: to.StringPtr("*"), 296 Access: network.SecurityRuleAccessAllow, 297 Priority: to.Int32Ptr(200), 298 Direction: network.SecurityRuleDirectionInbound, 299 }, 300 }, { 301 Name: to.StringPtr("machine-0-tcpcp-1"), 302 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 303 Protocol: network.SecurityRuleProtocolTCP, 304 DestinationPortRange: to.StringPtr("1000-2000"), 305 SourceAddressPrefix: to.StringPtr("*"), 306 Access: network.SecurityRuleAccessAllow, 307 Priority: to.Int32Ptr(201), 308 Direction: network.SecurityRuleDirectionInbound, 309 }, 310 }, { 311 Name: to.StringPtr("machine-0-tcpcp-2"), 312 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 313 Protocol: network.SecurityRuleProtocolTCP, 314 DestinationPortRange: to.StringPtr("1000-2000"), 315 SourceAddressPrefix: to.StringPtr("192.168.1.0/24"), 316 Access: network.SecurityRuleAccessAllow, 317 Priority: to.Int32Ptr(201), 318 Direction: network.SecurityRuleDirectionInbound, 319 }, 320 }, { 321 Name: to.StringPtr("machine-0-tcpcp-3"), 322 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 323 Protocol: network.SecurityRuleProtocolTCP, 324 DestinationPortRange: to.StringPtr("1000-2000"), 325 SourceAddressPrefix: to.StringPtr("10.0.0.0/24"), 326 Access: network.SecurityRuleAccessAllow, 327 Priority: to.Int32Ptr(201), 328 Direction: network.SecurityRuleDirectionInbound, 329 }, 330 }, { 331 Name: to.StringPtr("machine-0-http"), 332 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 333 Protocol: network.SecurityRuleProtocolAsterisk, 334 DestinationPortRange: to.StringPtr("80"), 335 Access: network.SecurityRuleAccessAllow, 336 Priority: to.Int32Ptr(202), 337 Direction: network.SecurityRuleDirectionInbound, 338 }, 339 }, { 340 Name: to.StringPtr("machine-00-ignored"), 341 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 342 Protocol: network.SecurityRuleProtocolTCP, 343 DestinationPortRange: to.StringPtr("80"), 344 Access: network.SecurityRuleAccessAllow, 345 Priority: to.Int32Ptr(202), 346 Direction: network.SecurityRuleDirectionInbound, 347 }, 348 }, { 349 Name: to.StringPtr("machine-0-ignored"), 350 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 351 Protocol: network.SecurityRuleProtocolTCP, 352 DestinationPortRange: to.StringPtr("80"), 353 Access: network.SecurityRuleAccessDeny, 354 Priority: to.Int32Ptr(202), 355 Direction: network.SecurityRuleDirectionInbound, 356 }, 357 }, { 358 Name: to.StringPtr("machine-0-ignored"), 359 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 360 Protocol: network.SecurityRuleProtocolTCP, 361 DestinationPortRange: to.StringPtr("80"), 362 Access: network.SecurityRuleAccessAllow, 363 Priority: to.Int32Ptr(202), 364 Direction: network.SecurityRuleDirectionOutbound, 365 }, 366 }, { 367 Name: to.StringPtr("machine-0-ignored"), 368 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 369 Protocol: network.SecurityRuleProtocolTCP, 370 DestinationPortRange: to.StringPtr("80"), 371 Access: network.SecurityRuleAccessAllow, 372 Priority: to.Int32Ptr(199), // internal range 373 Direction: network.SecurityRuleDirectionInbound, 374 }, 375 }}) 376 s.sender = azuretesting.Senders{nsgSender} 377 fwInst, ok := inst.(instances.InstanceFirewaller) 378 c.Assert(ok, gc.Equals, true) 379 380 rules, err := fwInst.IngressRules(s.callCtx, "0") 381 c.Assert(err, jc.ErrorIsNil) 382 c.Assert(rules, jc.DeepEquals, []jujunetwork.IngressRule{ 383 jujunetwork.MustNewIngressRule("tcp", 80, 80, "0.0.0.0/0"), 384 jujunetwork.MustNewIngressRule("tcp", 1000, 2000, "0.0.0.0/0", "192.168.1.0/24", "10.0.0.0/24"), 385 jujunetwork.MustNewIngressRule("udp", 0, 65535, "0.0.0.0/0"), 386 jujunetwork.MustNewIngressRule("udp", 80, 80, "0.0.0.0/0"), 387 }) 388 } 389 390 func (s *instanceSuite) TestInstanceClosePorts(c *gc.C) { 391 inst := s.getInstance(c) 392 fwInst, ok := inst.(instances.InstanceFirewaller) 393 c.Assert(ok, gc.Equals, true) 394 395 sender := mocks.NewSender() 396 notFoundSender := mocks.NewSender() 397 notFoundSender.AppendAndRepeatResponse(mocks.NewResponseWithStatus( 398 "rule not found", http.StatusNotFound, 399 ), 2) 400 s.sender = azuretesting.Senders{sender, notFoundSender, notFoundSender, notFoundSender} 401 402 err := fwInst.ClosePorts(s.callCtx, "0", []jujunetwork.IngressRule{ 403 jujunetwork.MustNewIngressRule("tcp", 1000, 1000), 404 jujunetwork.MustNewIngressRule("udp", 1000, 2000), 405 jujunetwork.MustNewIngressRule("udp", 1000, 2000, "192.168.1.0/24", "10.0.0.0/24"), 406 }) 407 c.Assert(err, jc.ErrorIsNil) 408 409 c.Assert(s.requests, gc.HasLen, 4) 410 c.Assert(s.requests[0].Method, gc.Equals, "DELETE") 411 c.Assert(s.requests[0].URL.Path, gc.Equals, securityRulePath("machine-0-tcp-1000")) 412 c.Assert(s.requests[1].Method, gc.Equals, "DELETE") 413 c.Assert(s.requests[1].URL.Path, gc.Equals, securityRulePath("machine-0-udp-1000-2000")) 414 c.Assert(s.requests[2].Method, gc.Equals, "DELETE") 415 c.Assert(s.requests[2].URL.Path, gc.Equals, securityRulePath("machine-0-udp-1000-2000-cidr-192-168-1-0-24")) 416 c.Assert(s.requests[3].Method, gc.Equals, "DELETE") 417 c.Assert(s.requests[3].URL.Path, gc.Equals, securityRulePath("machine-0-udp-1000-2000-cidr-10-0-0-0-24")) 418 } 419 420 func (s *instanceSuite) TestInstanceOpenPorts(c *gc.C) { 421 internalSubnetId := path.Join( 422 "/subscriptions", fakeSubscriptionId, 423 "resourceGroups/juju-testmodel-model-deadbeef-0bad-400d-8000-4b1d0d06f00d", 424 "providers/Microsoft.Network/virtualnetworks/juju-internal-network/subnets/juju-internal-subnet", 425 ) 426 ipConfiguration := network.InterfaceIPConfiguration{ 427 InterfaceIPConfigurationPropertiesFormat: &network.InterfaceIPConfigurationPropertiesFormat{ 428 Primary: to.BoolPtr(true), 429 PrivateIPAddress: to.StringPtr("10.0.0.4"), 430 Subnet: &network.Subnet{ 431 ID: to.StringPtr(internalSubnetId), 432 }, 433 }, 434 } 435 s.networkInterfaces = []network.Interface{ 436 makeNetworkInterface("nic-0", "machine-0", ipConfiguration), 437 } 438 439 inst := s.getInstance(c) 440 fwInst, ok := inst.(instances.InstanceFirewaller) 441 c.Assert(ok, gc.Equals, true) 442 443 okSender := mocks.NewSender() 444 okSender.AppendResponse(mocks.NewResponseWithContent("{}")) 445 nsgSender := networkSecurityGroupSender(nil) 446 s.sender = azuretesting.Senders{nsgSender, okSender, okSender, okSender, okSender} 447 448 err := fwInst.OpenPorts(s.callCtx, "0", []jujunetwork.IngressRule{ 449 jujunetwork.MustNewIngressRule("tcp", 1000, 1000), 450 jujunetwork.MustNewIngressRule("udp", 1000, 2000), 451 jujunetwork.MustNewIngressRule("tcp", 1000, 2000, "192.168.1.0/24", "10.0.0.0/24"), 452 }) 453 c.Assert(err, jc.ErrorIsNil) 454 455 c.Assert(s.requests, gc.HasLen, 5) 456 c.Assert(s.requests[0].Method, gc.Equals, "GET") 457 c.Assert(s.requests[0].URL.Path, gc.Equals, internalSecurityGroupPath) 458 c.Assert(s.requests[1].Method, gc.Equals, "PUT") 459 c.Assert(s.requests[1].URL.Path, gc.Equals, securityRulePath("machine-0-tcp-1000")) 460 assertRequestBody(c, s.requests[1], &network.SecurityRule{ 461 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 462 Description: to.StringPtr("1000/tcp from *"), 463 Protocol: network.SecurityRuleProtocolTCP, 464 SourcePortRange: to.StringPtr("*"), 465 SourceAddressPrefix: to.StringPtr("*"), 466 DestinationPortRange: to.StringPtr("1000"), 467 DestinationAddressPrefix: to.StringPtr("10.0.0.4"), 468 Access: network.SecurityRuleAccessAllow, 469 Priority: to.Int32Ptr(200), 470 Direction: network.SecurityRuleDirectionInbound, 471 }, 472 }) 473 c.Assert(s.requests[2].Method, gc.Equals, "PUT") 474 c.Assert(s.requests[2].URL.Path, gc.Equals, securityRulePath("machine-0-udp-1000-2000")) 475 assertRequestBody(c, s.requests[2], &network.SecurityRule{ 476 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 477 Description: to.StringPtr("1000-2000/udp from *"), 478 Protocol: network.SecurityRuleProtocolUDP, 479 SourcePortRange: to.StringPtr("*"), 480 SourceAddressPrefix: to.StringPtr("*"), 481 DestinationPortRange: to.StringPtr("1000-2000"), 482 DestinationAddressPrefix: to.StringPtr("10.0.0.4"), 483 Access: network.SecurityRuleAccessAllow, 484 Priority: to.Int32Ptr(201), 485 Direction: network.SecurityRuleDirectionInbound, 486 }, 487 }) 488 c.Assert(s.requests[3].Method, gc.Equals, "PUT") 489 c.Assert(s.requests[3].URL.Path, gc.Equals, securityRulePath("machine-0-tcp-1000-2000-cidr-192-168-1-0-24")) 490 assertRequestBody(c, s.requests[3], &network.SecurityRule{ 491 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 492 Description: to.StringPtr("1000-2000/tcp from 192.168.1.0/24"), 493 Protocol: network.SecurityRuleProtocolTCP, 494 SourcePortRange: to.StringPtr("*"), 495 SourceAddressPrefix: to.StringPtr("192.168.1.0/24"), 496 DestinationPortRange: to.StringPtr("1000-2000"), 497 DestinationAddressPrefix: to.StringPtr("10.0.0.4"), 498 Access: network.SecurityRuleAccessAllow, 499 Priority: to.Int32Ptr(202), 500 Direction: network.SecurityRuleDirectionInbound, 501 }, 502 }) 503 c.Assert(s.requests[4].Method, gc.Equals, "PUT") 504 c.Assert(s.requests[4].URL.Path, gc.Equals, securityRulePath("machine-0-tcp-1000-2000-cidr-10-0-0-0-24")) 505 assertRequestBody(c, s.requests[4], &network.SecurityRule{ 506 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 507 Description: to.StringPtr("1000-2000/tcp from 10.0.0.0/24"), 508 Protocol: network.SecurityRuleProtocolTCP, 509 SourcePortRange: to.StringPtr("*"), 510 SourceAddressPrefix: to.StringPtr("10.0.0.0/24"), 511 DestinationPortRange: to.StringPtr("1000-2000"), 512 DestinationAddressPrefix: to.StringPtr("10.0.0.4"), 513 Access: network.SecurityRuleAccessAllow, 514 Priority: to.Int32Ptr(203), 515 Direction: network.SecurityRuleDirectionInbound, 516 }, 517 }) 518 } 519 520 func (s *instanceSuite) TestInstanceOpenPortsAlreadyOpen(c *gc.C) { 521 internalSubnetId := path.Join( 522 "/subscriptions", fakeSubscriptionId, 523 "resourceGroups/juju-testmodel-model-deadbeef-0bad-400d-8000-4b1d0d06f00d", 524 "providers/Microsoft.Network/virtualnetworks/juju-internal-network/subnets/juju-internal-subnet", 525 ) 526 ipConfiguration := network.InterfaceIPConfiguration{ 527 InterfaceIPConfigurationPropertiesFormat: &network.InterfaceIPConfigurationPropertiesFormat{ 528 Primary: to.BoolPtr(true), 529 PrivateIPAddress: to.StringPtr("10.0.0.4"), 530 Subnet: &network.Subnet{ 531 ID: to.StringPtr(internalSubnetId), 532 }, 533 }, 534 } 535 s.networkInterfaces = []network.Interface{ 536 makeNetworkInterface("nic-0", "machine-0", ipConfiguration), 537 } 538 539 inst := s.getInstance(c) 540 fwInst, ok := inst.(instances.InstanceFirewaller) 541 c.Assert(ok, gc.Equals, true) 542 543 okSender := mocks.NewSender() 544 okSender.AppendResponse(mocks.NewResponseWithContent("{}")) 545 nsgSender := networkSecurityGroupSender([]network.SecurityRule{{ 546 Name: to.StringPtr("machine-0-tcp-1000"), 547 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 548 Protocol: network.SecurityRuleProtocolAsterisk, 549 DestinationPortRange: to.StringPtr("1000"), 550 Access: network.SecurityRuleAccessAllow, 551 Priority: to.Int32Ptr(202), 552 Direction: network.SecurityRuleDirectionInbound, 553 }, 554 }}) 555 s.sender = azuretesting.Senders{nsgSender, okSender, okSender} 556 557 err := fwInst.OpenPorts(s.callCtx, "0", []jujunetwork.IngressRule{ 558 jujunetwork.MustNewIngressRule("tcp", 1000, 1000), 559 jujunetwork.MustNewIngressRule("udp", 1000, 2000), 560 }) 561 c.Assert(err, jc.ErrorIsNil) 562 563 c.Assert(s.requests, gc.HasLen, 2) 564 c.Assert(s.requests[0].Method, gc.Equals, "GET") 565 c.Assert(s.requests[0].URL.Path, gc.Equals, internalSecurityGroupPath) 566 c.Assert(s.requests[1].Method, gc.Equals, "PUT") 567 c.Assert(s.requests[1].URL.Path, gc.Equals, securityRulePath("machine-0-udp-1000-2000")) 568 assertRequestBody(c, s.requests[1], &network.SecurityRule{ 569 SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ 570 Description: to.StringPtr("1000-2000/udp from *"), 571 Protocol: network.SecurityRuleProtocolUDP, 572 SourcePortRange: to.StringPtr("*"), 573 SourceAddressPrefix: to.StringPtr("*"), 574 DestinationPortRange: to.StringPtr("1000-2000"), 575 DestinationAddressPrefix: to.StringPtr("10.0.0.4"), 576 Access: network.SecurityRuleAccessAllow, 577 Priority: to.Int32Ptr(200), 578 Direction: network.SecurityRuleDirectionInbound, 579 }, 580 }) 581 } 582 583 func (s *instanceSuite) TestInstanceOpenPortsNoInternalAddress(c *gc.C) { 584 inst := s.getInstance(c) 585 fwInst, ok := inst.(instances.InstanceFirewaller) 586 c.Assert(ok, gc.Equals, true) 587 err := fwInst.OpenPorts(s.callCtx, "0", nil) 588 c.Assert(err, gc.ErrorMatches, "internal network address not found") 589 } 590 591 func (s *instanceSuite) TestAllInstances(c *gc.C) { 592 s.sender = s.getInstancesSender() 593 instances, err := s.env.AllInstances(s.callCtx) 594 c.Assert(err, jc.ErrorIsNil) 595 c.Assert(instances, gc.HasLen, 2) 596 c.Assert(instances[0].Id(), gc.Equals, instance.Id("machine-0")) 597 c.Assert(instances[1].Id(), gc.Equals, instance.Id("machine-1")) 598 } 599 600 func (s *instanceSuite) TestControllerInstances(c *gc.C) { 601 *(*(*s.deployments[0].Properties.Dependencies)[0].DependsOn)[0].ResourceName = "juju-controller" 602 s.sender = s.getInstancesSender() 603 ids, err := s.env.ControllerInstances(s.callCtx, "foo") 604 c.Assert(err, jc.ErrorIsNil) 605 c.Assert(ids, gc.HasLen, 1) 606 c.Assert(ids[0], gc.Equals, instance.Id("machine-0")) 607 } 608 609 var internalSecurityGroupPath = path.Join( 610 "/subscriptions", fakeSubscriptionId, 611 "resourceGroups", "juju-testmodel-model-"+testing.ModelTag.Id(), 612 "providers/Microsoft.Network/networkSecurityGroups/juju-internal-nsg", 613 ) 614 615 func securityRulePath(ruleName string) string { 616 return path.Join(internalSecurityGroupPath, "securityRules", ruleName) 617 }