github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/state/backups/restore_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  // +build !windows
     5  
     6  package backups
     7  
     8  import (
     9  	"fmt"
    10  	"io"
    11  	"net"
    12  	"os"
    13  	"path"
    14  	"strconv"
    15  	"strings"
    16  
    17  	"github.com/juju/names"
    18  	"github.com/juju/replicaset"
    19  	gitjujutesting "github.com/juju/testing"
    20  	jc "github.com/juju/testing/checkers"
    21  	gc "gopkg.in/check.v1"
    22  	"gopkg.in/mgo.v2"
    23  	"gopkg.in/mgo.v2/bson"
    24  
    25  	"github.com/juju/juju/agent"
    26  	"github.com/juju/juju/apiserver/params"
    27  	"github.com/juju/juju/mongo"
    28  	"github.com/juju/juju/state"
    29  	statetesting "github.com/juju/juju/state/testing"
    30  	coretesting "github.com/juju/juju/testing"
    31  	"github.com/juju/juju/utils/ssh"
    32  	"github.com/juju/juju/version"
    33  )
    34  
    35  var _ = gc.Suite(&RestoreSuite{})
    36  
    37  type RestoreSuite struct {
    38  	coretesting.BaseSuite
    39  	cwd       string
    40  	testFiles []string
    41  }
    42  
    43  func (r *RestoreSuite) SetUpSuite(c *gc.C) {
    44  	r.BaseSuite.SetUpSuite(c)
    45  }
    46  
    47  func (r *RestoreSuite) SetUpTest(c *gc.C) {
    48  	r.cwd = c.MkDir()
    49  	r.BaseSuite.SetUpTest(c)
    50  }
    51  
    52  func (r *RestoreSuite) createTestFiles(c *gc.C) {
    53  	tarDirE := path.Join(r.cwd, "TarDirectoryEmpty")
    54  	err := os.Mkdir(tarDirE, os.FileMode(0755))
    55  	c.Check(err, jc.ErrorIsNil)
    56  
    57  	tarDirP := path.Join(r.cwd, "TarDirectoryPopulated")
    58  	err = os.Mkdir(tarDirP, os.FileMode(0755))
    59  	c.Check(err, jc.ErrorIsNil)
    60  
    61  	tarSubFile1 := path.Join(tarDirP, "TarSubFile1")
    62  	tarSubFile1Handle, err := os.Create(tarSubFile1)
    63  	c.Check(err, jc.ErrorIsNil)
    64  	tarSubFile1Handle.WriteString("TarSubFile1")
    65  	tarSubFile1Handle.Close()
    66  
    67  	tarSubDir := path.Join(tarDirP, "TarDirectoryPopulatedSubDirectory")
    68  	err = os.Mkdir(tarSubDir, os.FileMode(0755))
    69  	c.Check(err, jc.ErrorIsNil)
    70  
    71  	tarFile1 := path.Join(r.cwd, "TarFile1")
    72  	tarFile1Handle, err := os.Create(tarFile1)
    73  	c.Check(err, jc.ErrorIsNil)
    74  	tarFile1Handle.WriteString("TarFile1")
    75  	tarFile1Handle.Close()
    76  
    77  	tarFile2 := path.Join(r.cwd, "TarFile2")
    78  	tarFile2Handle, err := os.Create(tarFile2)
    79  	c.Check(err, jc.ErrorIsNil)
    80  	tarFile2Handle.WriteString("TarFile2")
    81  	tarFile2Handle.Close()
    82  	r.testFiles = []string{tarDirE, tarDirP, tarFile1, tarFile2}
    83  }
    84  
    85  func (r *RestoreSuite) ensureAdminUser(c *gc.C, dialInfo *mgo.DialInfo, user, password string) (added bool, err error) {
    86  	_, portString, err := net.SplitHostPort(dialInfo.Addrs[0])
    87  	c.Assert(err, jc.ErrorIsNil)
    88  	port, err := strconv.Atoi(portString)
    89  	c.Assert(err, jc.ErrorIsNil)
    90  	return mongo.EnsureAdminUser(mongo.EnsureAdminUserParams{
    91  		DialInfo: dialInfo,
    92  		Port:     port,
    93  		User:     user,
    94  		Password: password,
    95  	})
    96  }
    97  
    98  func (r *RestoreSuite) TestReplicasetIsReset(c *gc.C) {
    99  	server := &gitjujutesting.MgoInstance{Params: []string{"--replSet", "juju"}}
   100  	err := server.Start(coretesting.Certs)
   101  	c.Assert(err, jc.ErrorIsNil)
   102  	defer server.DestroyWithLog()
   103  	mgoAddr := server.Addr()
   104  	dialInfo := server.DialInfo()
   105  
   106  	var cfg *replicaset.Config
   107  	dialInfo = server.DialInfo()
   108  	dialInfo.Addrs = []string{mgoAddr}
   109  	err = resetReplicaSet(dialInfo, mgoAddr)
   110  
   111  	session := server.MustDial()
   112  	defer session.Close()
   113  	cfg, err = replicaset.CurrentConfig(session)
   114  	c.Assert(err, jc.ErrorIsNil)
   115  	c.Assert(cfg.Members, gc.HasLen, 1)
   116  	c.Assert(cfg.Members[0].Address, gc.Equals, mgoAddr)
   117  }
   118  
   119  type backupConfigTests struct {
   120  	yamlFile      io.Reader
   121  	expectedError error
   122  	message       string
   123  }
   124  
   125  var yamlLines = []string{
   126  	"# format 1.18",
   127  	"bogus: aBogusValue",
   128  	"tag: aTag",
   129  	"statepassword: aStatePassword",
   130  	"oldpassword: anOldPassword",
   131  	"stateport: 1",
   132  	"apiport: 2",
   133  	"cacert: aLengthyCACert",
   134  }
   135  
   136  func (r *RestoreSuite) TestSetAgentAddressScript(c *gc.C) {
   137  	testServerAddresses := []string{
   138  		"FirstNewStateServerAddress:30303",
   139  		"SecondNewStateServerAddress:30304",
   140  		"ThirdNewStateServerAddress:30305",
   141  		"FourthNewStateServerAddress:30306",
   142  		"FiftNewStateServerAddress:30307",
   143  		"SixtNewStateServerAddress:30308",
   144  	}
   145  	for _, address := range testServerAddresses {
   146  		template := setAgentAddressScript(address)
   147  		expectedString := fmt.Sprintf("\t\ts/- .*(:[0-9]+)/- %s\\1/\n", address)
   148  		logger.Infof(fmt.Sprintf("Testing with address %q", address))
   149  		c.Assert(strings.Contains(template, expectedString), gc.Equals, true)
   150  	}
   151  }
   152  
   153  var caCertPEM = `
   154  -----BEGIN CERTIFICATE-----
   155  MIIBnTCCAUmgAwIBAgIBADALBgkqhkiG9w0BAQUwJjENMAsGA1UEChMEanVqdTEV
   156  MBMGA1UEAxMManVqdSB0ZXN0aW5nMB4XDTEyMTExNDE0Mzg1NFoXDTIyMTExNDE0
   157  NDM1NFowJjENMAsGA1UEChMEanVqdTEVMBMGA1UEAxMManVqdSB0ZXN0aW5nMFow
   158  CwYJKoZIhvcNAQEBA0sAMEgCQQCCOOpn9aWKcKr2GQGtygwD7PdfNe1I9BYiPAqa
   159  2I33F5+6PqFdfujUKvoyTJI6XG4Qo/CECaaN9smhyq9DxzMhAgMBAAGjZjBkMA4G
   160  A1UdDwEB/wQEAwIABDASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBQQDswP
   161  FQGeGMeTzPbHW62EZbbTJzAfBgNVHSMEGDAWgBQQDswPFQGeGMeTzPbHW62EZbbT
   162  JzALBgkqhkiG9w0BAQUDQQAqZzN0DqUyEfR8zIanozyD2pp10m9le+ODaKZDDNfH
   163  8cB2x26F1iZ8ccq5IC2LtQf1IKJnpTcYlLuDvW6yB96g
   164  -----END CERTIFICATE-----
   165  `
   166  
   167  func (r *RestoreSuite) TestNewDialInfo(c *gc.C) {
   168  	machineTag, err := names.ParseTag("machine-0")
   169  	c.Assert(err, jc.ErrorIsNil)
   170  
   171  	dataDir := path.Join(r.cwd, "dataDir")
   172  	err = os.Mkdir(dataDir, os.FileMode(0755))
   173  	c.Assert(err, jc.ErrorIsNil)
   174  
   175  	logDir := path.Join(r.cwd, "logDir")
   176  	err = os.Mkdir(logDir, os.FileMode(0755))
   177  	c.Assert(err, jc.ErrorIsNil)
   178  
   179  	configParams := agent.AgentConfigParams{
   180  		DataDir:           dataDir,
   181  		LogDir:            logDir,
   182  		UpgradedToVersion: version.Current.Number,
   183  		Tag:               machineTag,
   184  		Environment:       coretesting.EnvironmentTag,
   185  		Password:          "dummyPassword",
   186  		Nonce:             "dummyNonce",
   187  		StateAddresses:    []string{"fakeStateAddress:1234"},
   188  		APIAddresses:      []string{"fakeAPIAddress:12345"},
   189  		CACert:            caCertPEM,
   190  	}
   191  	statePort := 12345
   192  	privateAddress := "dummyPrivateAddress"
   193  	servingInfo := params.StateServingInfo{
   194  		APIPort:        1234,
   195  		StatePort:      statePort,
   196  		Cert:           caCertPEM,
   197  		CAPrivateKey:   "a ca key",
   198  		PrivateKey:     "a key",
   199  		SharedSecret:   "a secret",
   200  		SystemIdentity: "an identity",
   201  	}
   202  
   203  	conf, err := agent.NewStateMachineConfig(configParams, servingInfo)
   204  	c.Assert(err, jc.ErrorIsNil)
   205  
   206  	dialInfo, err := newDialInfo(privateAddress, conf)
   207  	c.Assert(err, jc.ErrorIsNil)
   208  	c.Assert(dialInfo.Username, gc.Equals, "admin")
   209  	c.Assert(dialInfo.Password, gc.Equals, "dummyPassword")
   210  	c.Assert(dialInfo.Direct, gc.Equals, true)
   211  	c.Assert(dialInfo.Addrs, gc.DeepEquals, []string{fmt.Sprintf("%s:%d", privateAddress, statePort)})
   212  }
   213  
   214  // TestUpdateMongoEntries has all the testing for this function to avoid creating multiple
   215  // mongo instances.
   216  func (r *RestoreSuite) TestUpdateMongoEntries(c *gc.C) {
   217  	server := &gitjujutesting.MgoInstance{}
   218  	err := server.Start(coretesting.Certs)
   219  	c.Assert(err, jc.ErrorIsNil)
   220  	defer server.DestroyWithLog()
   221  	dialInfo := server.DialInfo()
   222  	mgoAddr := server.Addr()
   223  	dialInfo.Addrs = []string{mgoAddr}
   224  	err = updateMongoEntries("1234", "0", "0", dialInfo)
   225  	c.Assert(err, gc.ErrorMatches, "cannot update machine 0 instance information: not found")
   226  
   227  	session := server.MustDial()
   228  	defer session.Close()
   229  
   230  	err = session.DB("juju").C("machines").Insert(bson.M{"machineid": "0", "instanceid": "0"})
   231  	c.Assert(err, jc.ErrorIsNil)
   232  
   233  	query := session.DB("juju").C("machines").Find(bson.M{"machineid": "0", "instanceid": "1234"})
   234  	n, err := query.Count()
   235  	c.Assert(err, jc.ErrorIsNil)
   236  	c.Assert(n, gc.Equals, 0)
   237  
   238  	err = updateMongoEntries("1234", "0", "0", dialInfo)
   239  	c.Assert(err, jc.ErrorIsNil)
   240  
   241  	query = session.DB("juju").C("machines").Find(bson.M{"machineid": "0", "instanceid": "1234"})
   242  	n, err = query.Count()
   243  	c.Assert(err, jc.ErrorIsNil)
   244  	c.Assert(n, gc.Equals, 1)
   245  }
   246  
   247  func (r *RestoreSuite) TestNewConnection(c *gc.C) {
   248  	server := &gitjujutesting.MgoInstance{}
   249  	err := server.Start(coretesting.Certs)
   250  	c.Assert(err, jc.ErrorIsNil)
   251  	defer server.DestroyWithLog()
   252  
   253  	st := statetesting.Initialize(c, names.NewLocalUserTag("test-admin"), nil, nil)
   254  	c.Assert(st.Close(), jc.ErrorIsNil)
   255  
   256  	r.PatchValue(&mongoDefaultDialOpts, statetesting.NewDialOpts)
   257  	r.PatchValue(&environsNewStatePolicy, func() state.Policy { return nil })
   258  	st, err = newStateConnection(st.EnvironTag(), statetesting.NewMongoInfo())
   259  	c.Assert(err, jc.ErrorIsNil)
   260  	c.Assert(st.Close(), jc.ErrorIsNil)
   261  }
   262  
   263  func (r *RestoreSuite) TestRunViaSSH(c *gc.C) {
   264  	var (
   265  		passedAddress string
   266  		passedArgs    []string
   267  	)
   268  	fakeSSHCommand := func(address string, args []string, options *ssh.Options) *ssh.Cmd {
   269  		passedAddress = address
   270  		passedArgs = args
   271  		return ssh.Command("", []string{"ls"}, &ssh.Options{})
   272  	}
   273  
   274  	r.PatchValue(&sshCommand, fakeSSHCommand)
   275  	runViaSSH("invalidAddress", "invalidScript")
   276  	c.Assert(passedAddress, gc.Equals, "ubuntu@invalidAddress")
   277  	c.Assert(passedArgs, gc.DeepEquals, []string{"sudo", "-n", "bash", "-c 'invalidScript'"})
   278  }