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 }