github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/environs/utils.go (about)

     1  package environs
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names"
     9  	"github.com/juju/utils"
    10  
    11  	"github.com/juju/juju/api"
    12  	"github.com/juju/juju/environs/storage"
    13  	"github.com/juju/juju/instance"
    14  	"github.com/juju/juju/network"
    15  	"github.com/juju/juju/state"
    16  )
    17  
    18  // LegacyStorage creates an Environ from the config in state and returns
    19  // its provider storage interface if it supports one. If the environment
    20  // does not support provider storage, then it will return an error
    21  // satisfying errors.IsNotSupported.
    22  func LegacyStorage(st *state.State) (storage.Storage, error) {
    23  	envConfig, err := st.EnvironConfig()
    24  	if err != nil {
    25  		return nil, fmt.Errorf("cannot get environment config: %v", err)
    26  	}
    27  	env, err := New(envConfig)
    28  	if err != nil {
    29  		return nil, fmt.Errorf("cannot access environment: %v", err)
    30  	}
    31  	if env, ok := env.(EnvironStorage); ok {
    32  		return env.Storage(), nil
    33  	}
    34  	errmsg := fmt.Sprintf("%s provider does not support provider storage", envConfig.Type())
    35  	return nil, errors.NewNotSupported(nil, errmsg)
    36  }
    37  
    38  // AddressesRefreshAttempt is the attempt strategy used when
    39  // refreshing instance addresses.
    40  var AddressesRefreshAttempt = utils.AttemptStrategy{
    41  	Total: 3 * time.Minute,
    42  	Delay: 1 * time.Second,
    43  }
    44  
    45  // getAddresses queries and returns the Addresses for the given instances,
    46  // ignoring nil instances or ones without addresses.
    47  func getAddresses(instances []instance.Instance) []network.Address {
    48  	var allAddrs []network.Address
    49  	for _, inst := range instances {
    50  		if inst == nil {
    51  			continue
    52  		}
    53  		addrs, err := inst.Addresses()
    54  		if err != nil {
    55  			logger.Debugf(
    56  				"failed to get addresses for %v: %v (ignoring)",
    57  				inst.Id(), err,
    58  			)
    59  			continue
    60  		}
    61  		allAddrs = append(allAddrs, addrs...)
    62  	}
    63  	return allAddrs
    64  }
    65  
    66  // waitAnyInstanceAddresses waits for at least one of the instances
    67  // to have addresses, and returns them.
    68  func waitAnyInstanceAddresses(
    69  	env Environ,
    70  	instanceIds []instance.Id,
    71  ) ([]network.Address, error) {
    72  	var addrs []network.Address
    73  	for a := AddressesRefreshAttempt.Start(); len(addrs) == 0 && a.Next(); {
    74  		instances, err := env.Instances(instanceIds)
    75  		if err != nil && err != ErrPartialInstances {
    76  			logger.Debugf("error getting state instances: %v", err)
    77  			return nil, err
    78  		}
    79  		addrs = getAddresses(instances)
    80  	}
    81  	if len(addrs) == 0 {
    82  		return nil, errors.NotFoundf("addresses for %v", instanceIds)
    83  	}
    84  	return addrs, nil
    85  }
    86  
    87  // APIInfo returns an api.Info for the environment. The result is populated
    88  // with addresses and CA certificate, but no tag or password.
    89  func APIInfo(env Environ) (*api.Info, error) {
    90  	instanceIds, err := env.StateServerInstances()
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  	logger.Debugf("StateServerInstances returned: %v", instanceIds)
    95  	addrs, err := waitAnyInstanceAddresses(env, instanceIds)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	config := env.Config()
   100  	cert, hasCert := config.CACert()
   101  	if !hasCert {
   102  		return nil, errors.New("config has no CACert")
   103  	}
   104  	apiPort := config.APIPort()
   105  	apiAddrs := network.HostPortsToStrings(
   106  		network.AddressesWithPort(addrs, apiPort),
   107  	)
   108  	uuid, uuidSet := config.UUID()
   109  	if !uuidSet {
   110  		return nil, errors.New("config has no UUID")
   111  	}
   112  	envTag := names.NewEnvironTag(uuid)
   113  	apiInfo := &api.Info{Addrs: apiAddrs, CACert: cert, EnvironTag: envTag}
   114  	return apiInfo, nil
   115  }