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