github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/environs/utils.go (about)

     1  package environs
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/juju/errors"
     7  	"github.com/juju/names"
     8  	"github.com/juju/utils"
     9  
    10  	"github.com/juju/juju/api"
    11  	"github.com/juju/juju/instance"
    12  	"github.com/juju/juju/network"
    13  )
    14  
    15  // AddressesRefreshAttempt is the attempt strategy used when
    16  // refreshing instance addresses.
    17  var AddressesRefreshAttempt = utils.AttemptStrategy{
    18  	Total: 3 * time.Minute,
    19  	Delay: 1 * time.Second,
    20  }
    21  
    22  // getAddresses queries and returns the Addresses for the given instances,
    23  // ignoring nil instances or ones without addresses.
    24  func getAddresses(instances []instance.Instance) []network.Address {
    25  	var allAddrs []network.Address
    26  	for _, inst := range instances {
    27  		if inst == nil {
    28  			continue
    29  		}
    30  		addrs, err := inst.Addresses()
    31  		if err != nil {
    32  			logger.Debugf(
    33  				"failed to get addresses for %v: %v (ignoring)",
    34  				inst.Id(), err,
    35  			)
    36  			continue
    37  		}
    38  		allAddrs = append(allAddrs, addrs...)
    39  	}
    40  	return allAddrs
    41  }
    42  
    43  // waitAnyInstanceAddresses waits for at least one of the instances
    44  // to have addresses, and returns them.
    45  func waitAnyInstanceAddresses(
    46  	env Environ,
    47  	instanceIds []instance.Id,
    48  ) ([]network.Address, error) {
    49  	var addrs []network.Address
    50  	for a := AddressesRefreshAttempt.Start(); len(addrs) == 0 && a.Next(); {
    51  		instances, err := env.Instances(instanceIds)
    52  		if err != nil && err != ErrPartialInstances {
    53  			logger.Debugf("error getting state instances: %v", err)
    54  			return nil, err
    55  		}
    56  		addrs = getAddresses(instances)
    57  	}
    58  	if len(addrs) == 0 {
    59  		return nil, errors.NotFoundf("addresses for %v", instanceIds)
    60  	}
    61  	return addrs, nil
    62  }
    63  
    64  // APIInfo returns an api.Info for the environment. The result is populated
    65  // with addresses and CA certificate, but no tag or password.
    66  func APIInfo(env Environ) (*api.Info, error) {
    67  	instanceIds, err := env.ControllerInstances()
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  	logger.Debugf("ControllerInstances returned: %v", instanceIds)
    72  	addrs, err := waitAnyInstanceAddresses(env, instanceIds)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	config := env.Config()
    77  	cert, hasCert := config.CACert()
    78  	if !hasCert {
    79  		return nil, errors.New("config has no CACert")
    80  	}
    81  	apiPort := config.APIPort()
    82  	apiAddrs := network.HostPortsToStrings(
    83  		network.AddressesWithPort(addrs, apiPort),
    84  	)
    85  	modelTag := names.NewModelTag(config.UUID())
    86  	apiInfo := &api.Info{Addrs: apiAddrs, CACert: cert, ModelTag: modelTag}
    87  	return apiInfo, nil
    88  }
    89  
    90  // CheckProviderAPI returns an error if a simple API call
    91  // to check a basic response from the specified environ fails.
    92  func CheckProviderAPI(env Environ) error {
    93  	// We will make a simple API call to the provider
    94  	// to ensure the underlying substrate is ok.
    95  	_, err := env.AllInstances()
    96  	switch err {
    97  	case nil, ErrPartialInstances, ErrNoInstances:
    98  		return nil
    99  	}
   100  	return errors.Annotate(err, "cannot make API call to provider")
   101  }