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