github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/azure/upgrades_test.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package azure_test
     5  
     6  import (
     7  	"net/http"
     8  
     9  	"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-10-01/compute"
    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/azure-sdk-for-go/services/storage/mgmt/2018-07-01/storage"
    13  	"github.com/Azure/go-autorest/autorest/mocks"
    14  	"github.com/Azure/go-autorest/autorest/to"
    15  	jc "github.com/juju/testing/checkers"
    16  	gc "gopkg.in/check.v1"
    17  
    18  	"github.com/juju/juju/environs"
    19  	"github.com/juju/juju/environs/context"
    20  	"github.com/juju/juju/provider/azure"
    21  	"github.com/juju/juju/provider/azure/internal/armtemplates"
    22  	"github.com/juju/juju/provider/azure/internal/azuretesting"
    23  	"github.com/juju/juju/testing"
    24  )
    25  
    26  type environUpgradeSuite struct {
    27  	testing.BaseSuite
    28  
    29  	requests []*http.Request
    30  	sender   azuretesting.Senders
    31  	provider environs.EnvironProvider
    32  	env      environs.Environ
    33  
    34  	callCtx           *context.CloudCallContext
    35  	invalidCredential bool
    36  }
    37  
    38  var _ = gc.Suite(&environUpgradeSuite{})
    39  
    40  func (s *environUpgradeSuite) SetUpTest(c *gc.C) {
    41  	s.BaseSuite.SetUpTest(c)
    42  	s.sender = nil
    43  	s.requests = nil
    44  
    45  	s.provider = newProvider(c, azure.ProviderConfig{
    46  		Sender:                     azuretesting.NewSerialSender(&s.sender),
    47  		RequestInspector:           azuretesting.RequestRecorder(&s.requests),
    48  		RandomWindowsAdminPassword: func() string { return "sorandom" },
    49  	})
    50  	s.env = openEnviron(c, s.provider, &s.sender)
    51  	s.callCtx = &context.CloudCallContext{
    52  		InvalidateCredentialFunc: func(string) error {
    53  			s.invalidCredential = true
    54  			return nil
    55  		},
    56  	}
    57  }
    58  
    59  func (s *environUpgradeSuite) TestEnvironImplementsUpgrader(c *gc.C) {
    60  	c.Assert(s.env, gc.Implements, new(environs.Upgrader))
    61  }
    62  
    63  func (s *environUpgradeSuite) TestEnvironUpgradeOperations(c *gc.C) {
    64  	upgrader := s.env.(environs.Upgrader)
    65  	ops := upgrader.UpgradeOperations(s.callCtx, environs.UpgradeOperationsParams{})
    66  	c.Assert(ops, gc.HasLen, 1)
    67  	c.Assert(ops[0].TargetVersion, gc.Equals, 1)
    68  	c.Assert(ops[0].Steps, gc.HasLen, 1)
    69  	c.Assert(ops[0].Steps[0].Description(), gc.Equals, "Create common resource deployment")
    70  }
    71  
    72  func (s *environUpgradeSuite) TestEnvironUpgradeOperationCreateCommonDeployment(c *gc.C) {
    73  	upgrader := s.env.(environs.Upgrader)
    74  	op0 := upgrader.UpgradeOperations(s.callCtx, environs.UpgradeOperationsParams{})[0]
    75  
    76  	// The existing NSG has two rules: one for Juju API traffic,
    77  	// and an application-specific rule. Only the latter should
    78  	// be preserved; we will recreate the "builtin" SSH rule,
    79  	// and the API rule is not needed for non-controller models.
    80  	customRule := network.SecurityRule{
    81  		Name: to.StringPtr("machine-0-tcp-1234"),
    82  		SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{
    83  			Description:              to.StringPtr("custom rule"),
    84  			Protocol:                 network.SecurityRuleProtocolTCP,
    85  			SourceAddressPrefix:      to.StringPtr("*"),
    86  			SourcePortRange:          to.StringPtr("*"),
    87  			DestinationAddressPrefix: to.StringPtr("*"),
    88  			DestinationPortRange:     to.StringPtr("1234"),
    89  			Access:                   network.SecurityRuleAccessAllow,
    90  			Priority:                 to.Int32Ptr(102),
    91  			Direction:                network.SecurityRuleDirectionInbound,
    92  		},
    93  	}
    94  	securityRules := []network.SecurityRule{{
    95  		Name: to.StringPtr("JujuAPIInbound"),
    96  		SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{
    97  			Description:              to.StringPtr("Allow API connections to controller machines"),
    98  			Protocol:                 network.SecurityRuleProtocolTCP,
    99  			SourceAddressPrefix:      to.StringPtr("*"),
   100  			SourcePortRange:          to.StringPtr("*"),
   101  			DestinationAddressPrefix: to.StringPtr("192.168.16.0/20"),
   102  			DestinationPortRange:     to.StringPtr("17777"),
   103  			Access:                   network.SecurityRuleAccessAllow,
   104  			Priority:                 to.Int32Ptr(101),
   105  			Direction:                network.SecurityRuleDirectionInbound,
   106  		},
   107  	}, customRule}
   108  	nsg := network.SecurityGroup{
   109  		SecurityGroupPropertiesFormat: &network.SecurityGroupPropertiesFormat{
   110  			SecurityRules: &securityRules,
   111  		},
   112  	}
   113  
   114  	vmListSender := azuretesting.NewSenderWithValue(&compute.VirtualMachineListResult{})
   115  	vmListSender.PathPattern = ".*/virtualMachines"
   116  	nsgSender := azuretesting.NewSenderWithValue(&nsg)
   117  	nsgSender.PathPattern = ".*/networkSecurityGroups/juju-internal-nsg"
   118  	deploymentSender := azuretesting.NewSenderWithValue(&resources.Deployment{})
   119  	deploymentSender.PathPattern = ".*/deployments/common"
   120  	s.sender = append(s.sender, vmListSender, nsgSender, deploymentSender)
   121  	c.Assert(op0.Steps[0].Run(s.callCtx), jc.ErrorIsNil)
   122  	c.Assert(s.requests, gc.HasLen, 3)
   123  
   124  	expectedSecurityRules := []network.SecurityRule{{
   125  		Name: to.StringPtr("SSHInbound"),
   126  		SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{
   127  			Description:              to.StringPtr("Allow SSH access to all machines"),
   128  			Protocol:                 network.SecurityRuleProtocolTCP,
   129  			SourceAddressPrefix:      to.StringPtr("*"),
   130  			SourcePortRange:          to.StringPtr("*"),
   131  			DestinationAddressPrefix: to.StringPtr("*"),
   132  			DestinationPortRange:     to.StringPtr("22"),
   133  			Access:                   network.SecurityRuleAccessAllow,
   134  			Priority:                 to.Int32Ptr(100),
   135  			Direction:                network.SecurityRuleDirectionInbound,
   136  		},
   137  	}, customRule}
   138  	nsgId := `[resourceId('Microsoft.Network/networkSecurityGroups', 'juju-internal-nsg')]`
   139  	subnets := []network.Subnet{{
   140  		Name: to.StringPtr("juju-internal-subnet"),
   141  		SubnetPropertiesFormat: &network.SubnetPropertiesFormat{
   142  			AddressPrefix: to.StringPtr("192.168.0.0/20"),
   143  			NetworkSecurityGroup: &network.SecurityGroup{
   144  				ID: to.StringPtr(nsgId),
   145  			},
   146  		},
   147  	}, {
   148  		Name: to.StringPtr("juju-controller-subnet"),
   149  		SubnetPropertiesFormat: &network.SubnetPropertiesFormat{
   150  			AddressPrefix: to.StringPtr("192.168.16.0/20"),
   151  			NetworkSecurityGroup: &network.SecurityGroup{
   152  				ID: to.StringPtr(nsgId),
   153  			},
   154  		},
   155  	}}
   156  	addressPrefixes := []string{"192.168.0.0/20", "192.168.16.0/20"}
   157  	templateResources := []armtemplates.Resource{{
   158  		Type:     "Microsoft.Network/networkSecurityGroups",
   159  		Name:     "juju-internal-nsg",
   160  		Location: "westus",
   161  		Properties: &network.SecurityGroupPropertiesFormat{
   162  			SecurityRules: &expectedSecurityRules,
   163  		},
   164  	}, {
   165  		Type:     "Microsoft.Network/virtualNetworks",
   166  		Name:     "juju-internal-network",
   167  		Location: "westus",
   168  		Properties: &network.VirtualNetworkPropertiesFormat{
   169  			AddressSpace: &network.AddressSpace{&addressPrefixes},
   170  			Subnets:      &subnets,
   171  		},
   172  		DependsOn: []string{nsgId},
   173  	}, {
   174  		Type:     "Microsoft.Storage/storageAccounts",
   175  		Name:     storageAccountName,
   176  		Location: "westus",
   177  		StorageSku: &storage.Sku{
   178  			Name: storage.SkuName("Standard_LRS"),
   179  		},
   180  	}}
   181  
   182  	var actual resources.Deployment
   183  	unmarshalRequestBody(c, s.requests[2], &actual)
   184  	c.Assert(actual.Properties, gc.NotNil)
   185  	c.Assert(actual.Properties.Template, gc.NotNil)
   186  	resources, ok := actual.Properties.Template.(map[string]interface{})["resources"].([]interface{})
   187  	c.Assert(ok, jc.IsTrue)
   188  	c.Assert(resources, gc.HasLen, len(templateResources))
   189  }
   190  
   191  func (s *environUpgradeSuite) TestEnvironUpgradeOperationCreateCommonDeploymentControllerModel(c *gc.C) {
   192  	s.sender = nil
   193  	s.requests = nil
   194  	env := openEnviron(c, s.provider, &s.sender, testing.Attrs{"name": "controller"})
   195  	upgrader := env.(environs.Upgrader)
   196  
   197  	controllerTags := make(map[string]*string)
   198  	trueString := "true"
   199  	controllerTags["juju-is-controller"] = &trueString
   200  	vms := []compute.VirtualMachine{{
   201  		Tags: nil,
   202  	}, {
   203  		Tags: controllerTags,
   204  	}}
   205  	vmListSender := azuretesting.NewSenderWithValue(&compute.VirtualMachineListResult{
   206  		Value: &vms,
   207  	})
   208  	vmListSender.PathPattern = ".*/virtualMachines"
   209  	s.sender = append(s.sender, vmListSender)
   210  
   211  	op0 := upgrader.UpgradeOperations(s.callCtx, environs.UpgradeOperationsParams{})[0]
   212  	c.Assert(op0.Steps[0].Run(s.callCtx), jc.ErrorIsNil)
   213  }
   214  
   215  func (s *environUpgradeSuite) TestEnvironUpgradeOperationCreateCommonDeploymentControllerModelWithInvalidCredential(c *gc.C) {
   216  	s.sender = nil
   217  	s.requests = nil
   218  	env := openEnviron(c, s.provider, &s.sender, testing.Attrs{"name": "controller"})
   219  	upgrader := env.(environs.Upgrader)
   220  
   221  	controllerTags := make(map[string]*string)
   222  	trueString := "true"
   223  	controllerTags["juju-is-controller"] = &trueString
   224  
   225  	mockSender := mocks.NewSender()
   226  	mockSender.AppendResponse(mocks.NewResponseWithStatus("401 Unauthorized", http.StatusUnauthorized))
   227  	s.sender = append(s.sender, mockSender)
   228  
   229  	c.Assert(s.invalidCredential, jc.IsFalse)
   230  	op0 := upgrader.UpgradeOperations(s.callCtx, environs.UpgradeOperationsParams{})[0]
   231  	c.Assert(op0.Steps[0].Run(s.callCtx), gc.NotNil)
   232  	c.Assert(s.invalidCredential, jc.IsTrue)
   233  }