github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/juju/testing/instance.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package testing 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names" 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 12 "github.com/juju/juju/api" 13 "github.com/juju/juju/cloudconfig/instancecfg" 14 "github.com/juju/juju/constraints" 15 "github.com/juju/juju/environs" 16 "github.com/juju/juju/environs/config" 17 "github.com/juju/juju/environs/imagemetadata" 18 "github.com/juju/juju/environs/simplestreams" 19 "github.com/juju/juju/environs/tools" 20 "github.com/juju/juju/instance" 21 "github.com/juju/juju/mongo" 22 "github.com/juju/juju/network" 23 "github.com/juju/juju/testing" 24 coretools "github.com/juju/juju/tools" 25 ) 26 27 // FakeStateInfo holds information about no state - it will always 28 // give an error when connected to. The machine id gives the machine id 29 // of the machine to be started. 30 func FakeStateInfo(machineId string) *mongo.MongoInfo { 31 return &mongo.MongoInfo{ 32 Info: mongo.Info{ 33 Addrs: []string{"0.1.2.3:1234"}, 34 CACert: testing.CACert, 35 }, 36 Tag: names.NewMachineTag(machineId), 37 Password: "unimportant", 38 } 39 } 40 41 // FakeAPIInfo holds information about no state - it will always 42 // give an error when connected to. The machine id gives the machine id 43 // of the machine to be started. 44 func FakeAPIInfo(machineId string) *api.Info { 45 return &api.Info{ 46 Addrs: []string{"0.1.2.3:1234"}, 47 Tag: names.NewMachineTag(machineId), 48 Password: "unimportant", 49 CACert: testing.CACert, 50 ModelTag: testing.ModelTag, 51 } 52 } 53 54 // WaitAddresses waits until the specified instance has addresses, and returns them. 55 func WaitInstanceAddresses(env environs.Environ, instId instance.Id) ([]network.Address, error) { 56 for a := testing.LongAttempt.Start(); a.Next(); { 57 insts, err := env.Instances([]instance.Id{instId}) 58 if err != nil { 59 return nil, err 60 } 61 addresses, err := insts[0].Addresses() 62 if err != nil { 63 return nil, err 64 } 65 if len(addresses) > 0 { 66 return addresses, nil 67 } 68 } 69 return nil, errors.Errorf("timed out trying to get addresses for %v", instId) 70 } 71 72 // AssertStartInstance is a test helper function that starts an instance with a 73 // plausible but invalid configuration, and checks that it succeeds. 74 func AssertStartInstance( 75 c *gc.C, env environs.Environ, machineId string, 76 ) ( 77 instance.Instance, *instance.HardwareCharacteristics, 78 ) { 79 inst, hc, _, err := StartInstance(env, machineId) 80 c.Assert(err, jc.ErrorIsNil) 81 return inst, hc 82 } 83 84 // StartInstance is a test helper function that starts an instance with a plausible 85 // but invalid configuration, and returns the result of Environ.StartInstance. 86 func StartInstance( 87 env environs.Environ, machineId string, 88 ) ( 89 instance.Instance, *instance.HardwareCharacteristics, []network.InterfaceInfo, error, 90 ) { 91 return StartInstanceWithConstraints(env, machineId, constraints.Value{}) 92 } 93 94 // AssertStartInstanceWithConstraints is a test helper function that starts an instance 95 // with the given constraints, and a plausible but invalid configuration, and returns 96 // the result of Environ.StartInstance. 97 func AssertStartInstanceWithConstraints( 98 c *gc.C, env environs.Environ, machineId string, cons constraints.Value, 99 ) ( 100 instance.Instance, *instance.HardwareCharacteristics, 101 ) { 102 inst, hc, _, err := StartInstanceWithConstraints(env, machineId, cons) 103 c.Assert(err, jc.ErrorIsNil) 104 return inst, hc 105 } 106 107 // StartInstanceWithConstraints is a test helper function that starts an instance 108 // with the given constraints, and a plausible but invalid configuration, and returns 109 // the result of Environ.StartInstance. 110 func StartInstanceWithConstraints( 111 env environs.Environ, machineId string, cons constraints.Value, 112 ) ( 113 instance.Instance, *instance.HardwareCharacteristics, []network.InterfaceInfo, error, 114 ) { 115 params := environs.StartInstanceParams{Constraints: cons} 116 result, err := StartInstanceWithParams(env, machineId, params) 117 if err != nil { 118 return nil, nil, nil, errors.Trace(err) 119 } 120 return result.Instance, result.Hardware, result.NetworkInfo, nil 121 } 122 123 // StartInstanceWithParams is a test helper function that starts an instance 124 // with the given parameters, and a plausible but invalid configuration, and 125 // returns the result of Environ.StartInstance. The provided params's 126 // InstanceConfig and Tools field values will be ignored. 127 func StartInstanceWithParams( 128 env environs.Environ, machineId string, 129 params environs.StartInstanceParams, 130 ) ( 131 *environs.StartInstanceResult, error, 132 ) { 133 preferredSeries := config.PreferredSeries(env.Config()) 134 agentVersion, ok := env.Config().AgentVersion() 135 if !ok { 136 return nil, errors.New("missing agent version in model config") 137 } 138 filter := coretools.Filter{ 139 Number: agentVersion, 140 Series: preferredSeries, 141 } 142 if params.Constraints.Arch != nil { 143 filter.Arch = *params.Constraints.Arch 144 } 145 stream := tools.PreferredStream(&agentVersion, env.Config().Development(), env.Config().AgentStream()) 146 possibleTools, err := tools.FindTools(env, -1, -1, stream, filter) 147 if err != nil { 148 return nil, errors.Trace(err) 149 } 150 151 if params.ImageMetadata == nil { 152 if err := SetImageMetadata( 153 env, 154 possibleTools.AllSeries(), 155 possibleTools.Arches(), 156 ¶ms.ImageMetadata, 157 ); err != nil { 158 return nil, errors.Trace(err) 159 } 160 } 161 162 machineNonce := "fake_nonce" 163 stateInfo := FakeStateInfo(machineId) 164 apiInfo := FakeAPIInfo(machineId) 165 instanceConfig, err := instancecfg.NewInstanceConfig( 166 machineId, 167 machineNonce, 168 imagemetadata.ReleasedStream, 169 preferredSeries, 170 "", 171 true, 172 stateInfo, 173 apiInfo, 174 ) 175 if err != nil { 176 return nil, errors.Trace(err) 177 } 178 instanceConfig.Tags = instancecfg.InstanceTags(env.Config(), nil) 179 params.Tools = possibleTools 180 params.InstanceConfig = instanceConfig 181 return env.StartInstance(params) 182 } 183 184 func SetImageMetadata(env environs.Environ, series, arches []string, out *[]*imagemetadata.ImageMetadata) error { 185 hasRegion, ok := env.(simplestreams.HasRegion) 186 if !ok { 187 return nil 188 } 189 sources, err := environs.ImageMetadataSources(env) 190 if err != nil { 191 return errors.Trace(err) 192 } 193 region, err := hasRegion.Region() 194 if err != nil { 195 return errors.Trace(err) 196 } 197 imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{ 198 CloudSpec: region, 199 Series: series, 200 Arches: arches, 201 Stream: env.Config().ImageStream(), 202 }) 203 imageMetadata, _, err := imagemetadata.Fetch(sources, imageConstraint) 204 if err != nil { 205 return errors.Trace(err) 206 } 207 *out = imageMetadata 208 return nil 209 }