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  			&params.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  }