github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/jujud/agent/agenttest/agent.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package agenttest
     5  
     6  import (
     7  	"fmt"
     8  	"time"
     9  
    10  	"github.com/juju/cmd"
    11  	"github.com/juju/replicaset"
    12  	gitjujutesting "github.com/juju/testing"
    13  	jc "github.com/juju/testing/checkers"
    14  	"github.com/juju/utils/arch"
    15  	"github.com/juju/utils/series"
    16  	"github.com/juju/version"
    17  	gc "gopkg.in/check.v1"
    18  	"gopkg.in/juju/names.v2"
    19  	"gopkg.in/mgo.v2"
    20  
    21  	"github.com/juju/juju/agent"
    22  	agenttools "github.com/juju/juju/agent/tools"
    23  	"github.com/juju/juju/apiserver/params"
    24  	cmdutil "github.com/juju/juju/cmd/jujud/util"
    25  	"github.com/juju/juju/environs"
    26  	"github.com/juju/juju/environs/filestorage"
    27  	envtesting "github.com/juju/juju/environs/testing"
    28  	envtools "github.com/juju/juju/environs/tools"
    29  	"github.com/juju/juju/juju/testing"
    30  	"github.com/juju/juju/mongo"
    31  	"github.com/juju/juju/mongo/mongotest"
    32  	"github.com/juju/juju/network"
    33  	"github.com/juju/juju/state"
    34  	"github.com/juju/juju/state/stateenvirons"
    35  	coretesting "github.com/juju/juju/testing"
    36  	coretools "github.com/juju/juju/tools"
    37  	jujuversion "github.com/juju/juju/version"
    38  	"github.com/juju/juju/worker/peergrouper"
    39  )
    40  
    41  type patchingSuite interface {
    42  	PatchValue(interface{}, interface{})
    43  }
    44  
    45  // InstallFakeEnsureMongo creates a new FakeEnsureMongo, patching
    46  // out replicaset.CurrentConfig and cmdutil.EnsureMongoServer.
    47  func InstallFakeEnsureMongo(suite patchingSuite) *FakeEnsureMongo {
    48  	f := &FakeEnsureMongo{
    49  		ServiceInstalled: true,
    50  	}
    51  	suite.PatchValue(&mongo.IsServiceInstalled, f.IsServiceInstalled)
    52  	suite.PatchValue(&replicaset.CurrentConfig, f.CurrentConfig)
    53  	suite.PatchValue(&cmdutil.EnsureMongoServer, f.EnsureMongo)
    54  	return f
    55  }
    56  
    57  // FakeEnsureMongo provides test fakes for the functions used to
    58  // initialise MongoDB.
    59  type FakeEnsureMongo struct {
    60  	EnsureCount      int
    61  	InitiateCount    int
    62  	DataDir          string
    63  	OplogSize        int
    64  	Info             state.StateServingInfo
    65  	InitiateParams   peergrouper.InitiateMongoParams
    66  	Err              error
    67  	ServiceInstalled bool
    68  }
    69  
    70  func (f *FakeEnsureMongo) IsServiceInstalled() (bool, error) {
    71  	return f.ServiceInstalled, nil
    72  }
    73  
    74  func (f *FakeEnsureMongo) CurrentConfig(*mgo.Session) (*replicaset.Config, error) {
    75  	// Return a dummy replicaset config that's good enough to
    76  	// indicate that the replicaset is initiated.
    77  	return &replicaset.Config{
    78  		Members: []replicaset.Member{{}},
    79  	}, nil
    80  }
    81  
    82  func (f *FakeEnsureMongo) EnsureMongo(args mongo.EnsureServerParams) error {
    83  	f.EnsureCount++
    84  	f.DataDir, f.OplogSize = args.DataDir, args.OplogSize
    85  	f.Info = state.StateServingInfo{
    86  		APIPort:        args.APIPort,
    87  		StatePort:      args.StatePort,
    88  		Cert:           args.Cert,
    89  		PrivateKey:     args.PrivateKey,
    90  		CAPrivateKey:   args.CAPrivateKey,
    91  		SharedSecret:   args.SharedSecret,
    92  		SystemIdentity: args.SystemIdentity,
    93  	}
    94  	return f.Err
    95  }
    96  
    97  func (f *FakeEnsureMongo) InitiateMongo(p peergrouper.InitiateMongoParams) error {
    98  	f.InitiateCount++
    99  	f.InitiateParams = p
   100  	return nil
   101  }
   102  
   103  // agentSuite is a fixture to be used by agent test suites.
   104  type AgentSuite struct {
   105  	oldRestartDelay time.Duration
   106  	testing.JujuConnSuite
   107  }
   108  
   109  // PrimeAgent writes the configuration file and tools for an agent
   110  // with the given entity name. It returns the agent's configuration and the
   111  // current tools.
   112  func (s *AgentSuite) PrimeAgent(c *gc.C, tag names.Tag, password string) (agent.ConfigSetterWriter, *coretools.Tools) {
   113  	vers := version.Binary{
   114  		Number: jujuversion.Current,
   115  		Arch:   arch.HostArch(),
   116  		Series: series.HostSeries(),
   117  	}
   118  	return s.PrimeAgentVersion(c, tag, password, vers)
   119  }
   120  
   121  // PrimeAgentVersion writes the configuration file and tools with version
   122  // vers for an agent with the given entity name. It returns the agent's
   123  // configuration and the current tools.
   124  func (s *AgentSuite) PrimeAgentVersion(c *gc.C, tag names.Tag, password string, vers version.Binary) (agent.ConfigSetterWriter, *coretools.Tools) {
   125  	c.Logf("priming agent %s", tag.String())
   126  	stor, err := filestorage.NewFileStorageWriter(c.MkDir())
   127  	c.Assert(err, jc.ErrorIsNil)
   128  	agentTools := envtesting.PrimeTools(c, stor, s.DataDir(), "released", vers)
   129  	err = envtools.MergeAndWriteMetadata(stor, "released", "released", coretools.List{agentTools}, envtools.DoNotWriteMirrors)
   130  	tools1, err := agenttools.ChangeAgentTools(s.DataDir(), tag.String(), vers)
   131  	c.Assert(err, jc.ErrorIsNil)
   132  	c.Assert(tools1, gc.DeepEquals, agentTools)
   133  
   134  	stateInfo := s.MongoInfo(c)
   135  	apiInfo := s.APIInfo(c)
   136  	paths := agent.DefaultPaths
   137  	paths.DataDir = s.DataDir()
   138  	paths.MetricsSpoolDir = c.MkDir()
   139  	conf, err := agent.NewAgentConfig(
   140  		agent.AgentConfigParams{
   141  			Paths:             paths,
   142  			Tag:               tag,
   143  			UpgradedToVersion: vers.Number,
   144  			Password:          password,
   145  			Nonce:             agent.BootstrapNonce,
   146  			StateAddresses:    stateInfo.Addrs,
   147  			APIAddresses:      apiInfo.Addrs,
   148  			CACert:            stateInfo.CACert,
   149  			Controller:        coretesting.ControllerTag,
   150  			Model:             apiInfo.ModelTag,
   151  		})
   152  	c.Assert(err, jc.ErrorIsNil)
   153  	conf.SetPassword(password)
   154  	c.Assert(conf.Write(), gc.IsNil)
   155  	s.primeAPIHostPorts(c)
   156  	return conf, agentTools
   157  }
   158  
   159  // PrimeStateAgent writes the configuration file and tools for
   160  // a state agent with the given entity name. It returns the agent's
   161  // configuration and the current tools.
   162  func (s *AgentSuite) PrimeStateAgent(c *gc.C, tag names.Tag, password string) (agent.ConfigSetterWriter, *coretools.Tools) {
   163  	vers := version.Binary{
   164  		Number: jujuversion.Current,
   165  		Arch:   arch.HostArch(),
   166  		Series: series.HostSeries(),
   167  	}
   168  	return s.PrimeStateAgentVersion(c, tag, password, vers)
   169  }
   170  
   171  // PrimeStateAgentVersion writes the configuration file and tools with
   172  // version vers for a state agent with the given entity name. It
   173  // returns the agent's configuration and the current tools.
   174  func (s *AgentSuite) PrimeStateAgentVersion(c *gc.C, tag names.Tag, password string, vers version.Binary) (
   175  	agent.ConfigSetterWriter, *coretools.Tools,
   176  ) {
   177  	stor, err := filestorage.NewFileStorageWriter(c.MkDir())
   178  	c.Assert(err, jc.ErrorIsNil)
   179  	agentTools := envtesting.PrimeTools(c, stor, s.DataDir(), "released", vers)
   180  	tools1, err := agenttools.ChangeAgentTools(s.DataDir(), tag.String(), vers)
   181  	c.Assert(err, jc.ErrorIsNil)
   182  	c.Assert(tools1, gc.DeepEquals, agentTools)
   183  
   184  	conf := s.WriteStateAgentConfig(c, tag, password, vers, s.State.ModelTag())
   185  	s.primeAPIHostPorts(c)
   186  	return conf, agentTools
   187  }
   188  
   189  // WriteStateAgentConfig creates and writes a state agent config.
   190  func (s *AgentSuite) WriteStateAgentConfig(
   191  	c *gc.C,
   192  	tag names.Tag,
   193  	password string,
   194  	vers version.Binary,
   195  	modelTag names.ModelTag,
   196  ) agent.ConfigSetterWriter {
   197  	stateInfo := s.State.MongoConnectionInfo()
   198  	apiPort := gitjujutesting.FindTCPPort()
   199  	apiAddr := []string{fmt.Sprintf("localhost:%d", apiPort)}
   200  	conf, err := agent.NewStateMachineConfig(
   201  		agent.AgentConfigParams{
   202  			Paths:             agent.NewPathsWithDefaults(agent.Paths{DataDir: s.DataDir()}),
   203  			Tag:               tag,
   204  			UpgradedToVersion: vers.Number,
   205  			Password:          password,
   206  			Nonce:             agent.BootstrapNonce,
   207  			StateAddresses:    stateInfo.Addrs,
   208  			APIAddresses:      apiAddr,
   209  			CACert:            stateInfo.CACert,
   210  			Controller:        s.State.ControllerTag(),
   211  			Model:             modelTag,
   212  		},
   213  		params.StateServingInfo{
   214  			Cert:         coretesting.ServerCert,
   215  			PrivateKey:   coretesting.ServerKey,
   216  			CAPrivateKey: coretesting.CAKey,
   217  			StatePort:    gitjujutesting.MgoServer.Port(),
   218  			APIPort:      apiPort,
   219  		})
   220  	c.Assert(err, jc.ErrorIsNil)
   221  	conf.SetPassword(password)
   222  	c.Assert(conf.Write(), gc.IsNil)
   223  	return conf
   224  }
   225  
   226  func (s *AgentSuite) primeAPIHostPorts(c *gc.C) {
   227  	apiInfo := s.APIInfo(c)
   228  
   229  	c.Assert(apiInfo.Addrs, gc.HasLen, 1)
   230  	hostPorts, err := network.ParseHostPorts(apiInfo.Addrs[0])
   231  	c.Assert(err, jc.ErrorIsNil)
   232  
   233  	err = s.State.SetAPIHostPorts([][]network.HostPort{hostPorts})
   234  	c.Assert(err, jc.ErrorIsNil)
   235  
   236  	c.Logf("api host ports primed %#v", hostPorts)
   237  }
   238  
   239  // InitAgent initialises the given agent command with additional
   240  // arguments as provided.
   241  func (s *AgentSuite) InitAgent(c *gc.C, a cmd.Command, args ...string) {
   242  	args = append([]string{"--data-dir", s.DataDir()}, args...)
   243  	err := coretesting.InitCommand(a, args)
   244  	c.Assert(err, jc.ErrorIsNil)
   245  }
   246  
   247  func (s *AgentSuite) AssertCanOpenState(c *gc.C, tag names.Tag, dataDir string) {
   248  	config, err := agent.ReadConfig(agent.ConfigPath(dataDir, tag))
   249  	c.Assert(err, jc.ErrorIsNil)
   250  	info, ok := config.MongoInfo()
   251  	c.Assert(ok, jc.IsTrue)
   252  	st, err := state.Open(config.Model(), config.Controller(), info, mongotest.DialOpts(), stateenvirons.GetNewPolicyFunc(
   253  		stateenvirons.GetNewEnvironFunc(environs.New),
   254  	))
   255  	c.Assert(err, jc.ErrorIsNil)
   256  	st.Close()
   257  }
   258  
   259  func (s *AgentSuite) AssertCannotOpenState(c *gc.C, tag names.Tag, dataDir string) {
   260  	config, err := agent.ReadConfig(agent.ConfigPath(dataDir, tag))
   261  	c.Assert(err, jc.ErrorIsNil)
   262  	_, ok := config.MongoInfo()
   263  	c.Assert(ok, jc.IsFalse)
   264  }