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

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package azure
     5  
     6  import (
     7  	stdcontext "context"
     8  	"strings"
     9  
    10  	"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-10-01/compute"
    11  	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-08-01/network"
    12  	"github.com/Azure/go-autorest/autorest/to"
    13  	"github.com/juju/errors"
    14  
    15  	"github.com/juju/juju/environs"
    16  	"github.com/juju/juju/environs/context"
    17  	"github.com/juju/juju/environs/tags"
    18  	"github.com/juju/juju/provider/azure/internal/errorutils"
    19  )
    20  
    21  // UpgradeOperations is part of the upgrades.OperationSource interface.
    22  func (env *azureEnviron) UpgradeOperations(context.ProviderCallContext, environs.UpgradeOperationsParams) []environs.UpgradeOperation {
    23  	return []environs.UpgradeOperation{{
    24  		providerVersion1,
    25  		[]environs.UpgradeStep{
    26  			commonDeploymentUpgradeStep{env},
    27  		},
    28  	}}
    29  }
    30  
    31  // commonDeploymentUpgradeStep adds a "common" deployment to each
    32  // Environ corresponding to non-controller models.
    33  type commonDeploymentUpgradeStep struct {
    34  	env *azureEnviron
    35  }
    36  
    37  // Description is part of the environs.UpgradeStep interface.
    38  func (commonDeploymentUpgradeStep) Description() string {
    39  	return "Create common resource deployment"
    40  }
    41  
    42  // Run is part of the environs.UpgradeStep interface.
    43  func (step commonDeploymentUpgradeStep) Run(ctx context.ProviderCallContext) error {
    44  	env := step.env
    45  	isControllerEnviron, err := isControllerEnviron(env, ctx)
    46  	if err != nil {
    47  		return errors.Trace(err)
    48  	}
    49  	if isControllerEnviron {
    50  		// We only need to create the deployment for
    51  		// non-controller Environs.
    52  		return nil
    53  	}
    54  
    55  	// Identify the network security rules that exist already.
    56  	// We will add these, excluding the SSH/API rules, to the
    57  	// network security group template created in the deployment
    58  	// below.
    59  	nsgClient := network.SecurityGroupsClient{
    60  		BaseClient: env.network,
    61  	}
    62  	allRules, err := networkSecurityRules(nsgClient, env.resourceGroup)
    63  	if errors.IsNotFound(err) {
    64  		allRules = nil
    65  	} else if err != nil {
    66  		return errors.Trace(err)
    67  	}
    68  	rules := make([]network.SecurityRule, 0, len(allRules))
    69  	for _, rule := range allRules {
    70  		name := to.String(rule.Name)
    71  		if name == sshSecurityRuleName || strings.HasPrefix(name, apiSecurityRulePrefix) {
    72  			continue
    73  		}
    74  		rules = append(rules, rule)
    75  	}
    76  
    77  	env.mu.Lock()
    78  	storageAccountType := env.config.storageAccountType
    79  	env.mu.Unlock()
    80  	return env.createCommonResourceDeployment(ctx, nil, rules, storageAccountTemplateResource(
    81  		env.location, nil,
    82  		env.storageAccountName,
    83  		storageAccountType,
    84  	))
    85  }
    86  
    87  func isControllerEnviron(env *azureEnviron, ctx context.ProviderCallContext) (bool, error) {
    88  	// Look for a machine with the "juju-is-controller" tag set to "true".
    89  	client := compute.VirtualMachinesClient{env.compute}
    90  	sdkCtx := stdcontext.Background()
    91  	result, err := client.ListComplete(sdkCtx, env.resourceGroup)
    92  	if err != nil {
    93  		return false, errorutils.HandleCredentialError(errors.Annotate(err, "listing virtual machines"), ctx)
    94  	}
    95  
    96  	if result.Response().IsEmpty() {
    97  		// No machines implies this is not the controller model, as
    98  		// there must be a controller machine for the upgrades to be
    99  		// running!
   100  		return false, nil
   101  	}
   102  
   103  	for ; result.NotDone(); err = result.NextWithContext(sdkCtx) {
   104  		if err != nil {
   105  			return false, errors.Annotate(err, "iterating machines")
   106  		}
   107  		vm := result.Value()
   108  		if to.String(vm.Tags[tags.JujuIsController]) == "true" {
   109  			return true, nil
   110  		}
   111  	}
   112  	return false, nil
   113  }