github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/provisioner/broker_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package provisioner_test
     5  
     6  import (
     7  	"io/ioutil"
     8  	"net"
     9  	"path/filepath"
    10  
    11  	gitjujutesting "github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	"github.com/juju/utils/arch"
    14  	"github.com/juju/version"
    15  	gc "gopkg.in/check.v1"
    16  	"gopkg.in/juju/names.v2"
    17  
    18  	"github.com/juju/juju/apiserver/params"
    19  	"github.com/juju/juju/cloudconfig/instancecfg"
    20  	"github.com/juju/juju/constraints"
    21  	"github.com/juju/juju/environs"
    22  	"github.com/juju/juju/instance"
    23  	instancetest "github.com/juju/juju/instance/testing"
    24  	jujutesting "github.com/juju/juju/juju/testing"
    25  	"github.com/juju/juju/network"
    26  	"github.com/juju/juju/status"
    27  	coretesting "github.com/juju/juju/testing"
    28  	coretools "github.com/juju/juju/tools"
    29  	"github.com/juju/juju/worker/provisioner"
    30  )
    31  
    32  type fakeAddr struct{ value string }
    33  
    34  func (f *fakeAddr) Network() string { return "net" }
    35  func (f *fakeAddr) String() string {
    36  	if f.value != "" {
    37  		return f.value
    38  	}
    39  	return "fakeAddr"
    40  }
    41  
    42  var _ net.Addr = (*fakeAddr)(nil)
    43  
    44  type fakeAPI struct {
    45  	*gitjujutesting.Stub
    46  
    47  	fakeContainerConfig params.ContainerConfig
    48  	fakeInterfaceInfo   network.InterfaceInfo
    49  }
    50  
    51  var _ provisioner.APICalls = (*fakeAPI)(nil)
    52  
    53  var fakeInterfaceInfo network.InterfaceInfo = network.InterfaceInfo{
    54  	DeviceIndex:    0,
    55  	MACAddress:     "aa:bb:cc:dd:ee:ff",
    56  	CIDR:           "0.1.2.0/24",
    57  	InterfaceName:  "dummy0",
    58  	Address:        network.NewAddress("0.1.2.3"),
    59  	GatewayAddress: network.NewAddress("0.1.2.1"),
    60  	// Explicitly set only DNSServers, but not DNSSearchDomains to test this is
    61  	// detected and the latter populated by parsing the fake resolv.conf created
    62  	// by patchResolvConf(). See LP bug http://pad.lv/1575940 for more info.
    63  	DNSServers:       network.NewAddresses("ns1.dummy"),
    64  	DNSSearchDomains: nil,
    65  }
    66  
    67  var fakeContainerConfig = params.ContainerConfig{
    68  	UpdateBehavior:          &params.UpdateBehavior{true, true},
    69  	ProviderType:            "fake",
    70  	AuthorizedKeys:          coretesting.FakeAuthKeys,
    71  	SSLHostnameVerification: true,
    72  }
    73  
    74  func NewFakeAPI() *fakeAPI {
    75  	return &fakeAPI{
    76  		Stub:                &gitjujutesting.Stub{},
    77  		fakeContainerConfig: fakeContainerConfig,
    78  		fakeInterfaceInfo:   fakeInterfaceInfo,
    79  	}
    80  }
    81  
    82  func (f *fakeAPI) ContainerConfig() (params.ContainerConfig, error) {
    83  	f.MethodCall(f, "ContainerConfig")
    84  	if err := f.NextErr(); err != nil {
    85  		return params.ContainerConfig{}, err
    86  	}
    87  	return f.fakeContainerConfig, nil
    88  }
    89  
    90  func (f *fakeAPI) PrepareContainerInterfaceInfo(tag names.MachineTag) ([]network.InterfaceInfo, error) {
    91  	f.MethodCall(f, "PrepareContainerInterfaceInfo", tag)
    92  	if err := f.NextErr(); err != nil {
    93  		return nil, err
    94  	}
    95  	return []network.InterfaceInfo{f.fakeInterfaceInfo}, nil
    96  }
    97  
    98  func (f *fakeAPI) GetContainerInterfaceInfo(tag names.MachineTag) ([]network.InterfaceInfo, error) {
    99  	f.MethodCall(f, "GetContainerInterfaceInfo", tag)
   100  	if err := f.NextErr(); err != nil {
   101  		return nil, err
   102  	}
   103  	return []network.InterfaceInfo{f.fakeInterfaceInfo}, nil
   104  }
   105  
   106  func (f *fakeAPI) ReleaseContainerAddresses(tag names.MachineTag) error {
   107  	f.MethodCall(f, "ReleaseContainerAddresses", tag)
   108  	if err := f.NextErr(); err != nil {
   109  		return err
   110  	}
   111  	return nil
   112  }
   113  
   114  type patcher interface {
   115  	PatchValue(destination, source interface{})
   116  }
   117  
   118  func patchResolvConf(s patcher, c *gc.C) {
   119  	const fakeConf = `
   120  nameserver ns1.dummy
   121  search dummy invalid
   122  nameserver ns2.dummy
   123  `
   124  
   125  	fakeResolvConf := filepath.Join(c.MkDir(), "fakeresolv.conf")
   126  	err := ioutil.WriteFile(fakeResolvConf, []byte(fakeConf), 0644)
   127  	c.Assert(err, jc.ErrorIsNil)
   128  	s.PatchValue(provisioner.ResolvConf, fakeResolvConf)
   129  }
   130  
   131  func instancesFromResults(results ...*environs.StartInstanceResult) []instance.Instance {
   132  	instances := make([]instance.Instance, len(results))
   133  	for i := range results {
   134  		instances[i] = results[i].Instance
   135  	}
   136  	return instances
   137  }
   138  
   139  func assertInstancesStarted(c *gc.C, broker environs.InstanceBroker, results ...*environs.StartInstanceResult) {
   140  	allInstances, err := broker.AllInstances()
   141  	c.Assert(err, jc.ErrorIsNil)
   142  	instancetest.MatchInstances(c, allInstances, instancesFromResults(results...)...)
   143  }
   144  
   145  func makeInstanceConfig(c *gc.C, s patcher, machineId string) *instancecfg.InstanceConfig {
   146  	machineNonce := "fake-nonce"
   147  	// To isolate the tests from the host's architecture, we override it here.
   148  	s.PatchValue(&arch.HostArch, func() string { return arch.AMD64 })
   149  	apiInfo := jujutesting.FakeAPIInfo(machineId)
   150  	instanceConfig, err := instancecfg.NewInstanceConfig(coretesting.ControllerTag, machineId, machineNonce, "released", "quantal", apiInfo)
   151  	c.Assert(err, jc.ErrorIsNil)
   152  	return instanceConfig
   153  }
   154  
   155  func makePossibleTools() coretools.List {
   156  	return coretools.List{&coretools.Tools{
   157  		Version: version.MustParseBinary("2.3.4-quantal-amd64"),
   158  		URL:     "http://tools.testing.invalid/2.3.4-quantal-amd64.tgz",
   159  	}, {
   160  		// non-host-arch tools should be filtered out by StartInstance
   161  		Version: version.MustParseBinary("2.3.4-quantal-arm64"),
   162  		URL:     "http://tools.testing.invalid/2.3.4-quantal-arm64.tgz",
   163  	}}
   164  }
   165  
   166  func makeNoOpStatusCallback() func(settableStatus status.Status, info string, data map[string]interface{}) error {
   167  	return func(_ status.Status, _ string, _ map[string]interface{}) error {
   168  		return nil
   169  	}
   170  }
   171  
   172  func callStartInstance(c *gc.C, s patcher, broker environs.InstanceBroker, machineId string) *environs.StartInstanceResult {
   173  	result, err := broker.StartInstance(environs.StartInstanceParams{
   174  		Constraints:    constraints.Value{},
   175  		Tools:          makePossibleTools(),
   176  		InstanceConfig: makeInstanceConfig(c, s, machineId),
   177  		StatusCallback: makeNoOpStatusCallback(),
   178  	})
   179  	c.Assert(err, jc.ErrorIsNil)
   180  	return result
   181  }
   182  
   183  func callMaintainInstance(c *gc.C, s patcher, broker environs.InstanceBroker, machineId string) {
   184  	err := broker.MaintainInstance(environs.StartInstanceParams{
   185  		Constraints:    constraints.Value{},
   186  		Tools:          makePossibleTools(),
   187  		InstanceConfig: makeInstanceConfig(c, s, machineId),
   188  		StatusCallback: makeNoOpStatusCallback(),
   189  	})
   190  	c.Assert(err, jc.ErrorIsNil)
   191  }