github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/cmd/juju/backups/restore_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package backups_test
     5  
     6  import (
     7  	"io"
     8  
     9  	"github.com/juju/errors"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	apibackups "github.com/juju/juju/api/backups"
    14  	"github.com/juju/juju/apiserver/params"
    15  	"github.com/juju/juju/cloud"
    16  	"github.com/juju/juju/cmd/juju/backups"
    17  	"github.com/juju/juju/environs"
    18  	"github.com/juju/juju/environs/bootstrap"
    19  	"github.com/juju/juju/environs/config"
    20  	"github.com/juju/juju/instance"
    21  	"github.com/juju/juju/jujuclient"
    22  	"github.com/juju/juju/jujuclient/jujuclienttesting"
    23  	"github.com/juju/juju/network"
    24  	_ "github.com/juju/juju/provider/dummy"
    25  	"github.com/juju/juju/testing"
    26  )
    27  
    28  type restoreSuite struct {
    29  	BaseBackupsSuite
    30  	store *jujuclienttesting.MemStore
    31  }
    32  
    33  var _ = gc.Suite(&restoreSuite{})
    34  
    35  func (s *restoreSuite) SetUpTest(c *gc.C) {
    36  	s.BaseBackupsSuite.SetUpTest(c)
    37  	s.store = jujuclienttesting.NewMemStore()
    38  	s.store.Controllers["testing"] = jujuclient.ControllerDetails{
    39  		ControllerUUID: testing.ModelTag.Id(),
    40  		CACert:         testing.CACert,
    41  	}
    42  	s.store.Models["testing"] = jujuclient.ControllerAccountModels{
    43  		AccountModels: map[string]*jujuclient.AccountModels{
    44  			"admin@local": {
    45  				Models: map[string]jujuclient.ModelDetails{
    46  					"admin": {"test1-uuid"},
    47  				},
    48  				CurrentModel: "admin",
    49  			},
    50  		},
    51  	}
    52  	s.store.Accounts["testing"] = &jujuclient.ControllerAccounts{
    53  		Accounts: map[string]jujuclient.AccountDetails{
    54  			"admin@local": {
    55  				User:     "current-user@local",
    56  				Password: "old-password",
    57  			},
    58  		},
    59  		CurrentAccount: "admin@local",
    60  	}
    61  	s.store.BootstrapConfig["testing"] = jujuclient.BootstrapConfig{
    62  		Cloud: "dummy",
    63  		//Credential: "me",
    64  		Config: map[string]interface{}{
    65  			"type": "dummy",
    66  			"name": "admin",
    67  		},
    68  	}
    69  	s.store.Credentials["dummy"] = cloud.CloudCredential{
    70  		AuthCredentials: map[string]cloud.Credential{
    71  			"me": cloud.NewCredential(cloud.UserPassAuthType, map[string]string{
    72  				"username": "user",
    73  				"password": "sekret",
    74  			}),
    75  		},
    76  	}
    77  }
    78  
    79  func (s *restoreSuite) TestRestoreArgs(c *gc.C) {
    80  	s.command = backups.NewRestoreCommandForTest(s.store, nil, nil, nil)
    81  	_, err := testing.RunCommand(c, s.command, "restore")
    82  	c.Assert(err, gc.ErrorMatches, "you must specify either a file or a backup id.")
    83  
    84  	_, err = testing.RunCommand(c, s.command, "restore", "--id", "anid", "--file", "afile")
    85  	c.Assert(err, gc.ErrorMatches, "you must specify either a file or a backup id but not both.")
    86  
    87  	_, err = testing.RunCommand(c, s.command, "restore", "--id", "anid", "-b")
    88  	c.Assert(err, gc.ErrorMatches, "it is not possible to rebootstrap and restore from an id.")
    89  }
    90  
    91  // TODO(wallyworld) - add more api related unit tests
    92  type mockRestoreAPI struct {
    93  	backups.RestoreAPI
    94  }
    95  
    96  func (*mockRestoreAPI) Close() error {
    97  	return nil
    98  }
    99  
   100  func (*mockRestoreAPI) RestoreReader(io.ReadSeeker, *params.BackupsMetadataResult, apibackups.ClientConnection) error {
   101  	return nil
   102  }
   103  
   104  type mockArchiveReader struct {
   105  	backups.ArchiveReader
   106  }
   107  
   108  func (*mockArchiveReader) Close() error {
   109  	return nil
   110  }
   111  
   112  func (s *restoreSuite) TestRestoreReboostrapControllerExists(c *gc.C) {
   113  	fakeEnv := fakeEnviron{controllerInstances: []instance.Id{"1"}}
   114  	s.command = backups.NewRestoreCommandForTest(
   115  		s.store, &mockRestoreAPI{},
   116  		func(string) (backups.ArchiveReader, *params.BackupsMetadataResult, error) {
   117  			return &mockArchiveReader{}, &params.BackupsMetadataResult{}, nil
   118  		},
   119  		func(string, *params.BackupsMetadataResult) (environs.Environ, error) {
   120  			return fakeEnv, nil
   121  		})
   122  	_, err := testing.RunCommand(c, s.command, "restore", "--file", "afile", "-b")
   123  	c.Assert(err, gc.ErrorMatches, ".*still seems to exist.*")
   124  }
   125  
   126  func (s *restoreSuite) TestRestoreReboostrapNoControllers(c *gc.C) {
   127  	fakeEnv := fakeEnviron{}
   128  	s.command = backups.NewRestoreCommandForTest(
   129  		s.store, &mockRestoreAPI{},
   130  		func(string) (backups.ArchiveReader, *params.BackupsMetadataResult, error) {
   131  			return &mockArchiveReader{}, &params.BackupsMetadataResult{}, nil
   132  		},
   133  		func(string, *params.BackupsMetadataResult) (environs.Environ, error) {
   134  			return fakeEnv, nil
   135  		})
   136  	s.PatchValue(&backups.BootstrapFunc, func(ctx environs.BootstrapContext, environ environs.Environ, args bootstrap.BootstrapParams) error {
   137  		return errors.New("failed to bootstrap new controller")
   138  	})
   139  
   140  	_, err := testing.RunCommand(c, s.command, "restore", "--file", "afile", "-b")
   141  	c.Assert(err, gc.ErrorMatches, ".*failed to bootstrap new controller")
   142  }
   143  
   144  func (s *restoreSuite) TestRestoreReboostrapReadsMetadata(c *gc.C) {
   145  	metadata := params.BackupsMetadataResult{
   146  		CACert:       testing.CACert,
   147  		CAPrivateKey: testing.CAKey,
   148  	}
   149  	s.command = backups.NewRestoreCommandForTest(
   150  		s.store, &mockRestoreAPI{},
   151  		func(string) (backups.ArchiveReader, *params.BackupsMetadataResult, error) {
   152  			return &mockArchiveReader{}, &metadata, nil
   153  		},
   154  		nil)
   155  	s.PatchValue(&backups.BootstrapFunc, func(ctx environs.BootstrapContext, environ environs.Environ, args bootstrap.BootstrapParams) error {
   156  		attr := environ.Config().AllAttrs()
   157  		c.Assert(attr["ca-cert"], gc.Equals, testing.CACert)
   158  		return errors.New("failed to bootstrap new controller")
   159  	})
   160  
   161  	_, err := testing.RunCommand(c, s.command, "restore", "-m", "testing:test1", "--file", "afile", "-b")
   162  	c.Assert(err, gc.ErrorMatches, ".*failed to bootstrap new controller")
   163  }
   164  
   165  func (s *restoreSuite) TestRestoreReboostrapWritesUpdatedControllerInfo(c *gc.C) {
   166  	metadata := params.BackupsMetadataResult{
   167  		CACert:       testing.CACert,
   168  		CAPrivateKey: testing.CAKey,
   169  	}
   170  	fakeEnv := fakeEnviron{}
   171  	s.command = backups.NewRestoreCommandForTest(
   172  		s.store, &mockRestoreAPI{},
   173  		func(string) (backups.ArchiveReader, *params.BackupsMetadataResult, error) {
   174  			return &mockArchiveReader{}, &metadata, nil
   175  		},
   176  		func(string, *params.BackupsMetadataResult) (environs.Environ, error) {
   177  			return fakeEnv, nil
   178  		})
   179  	s.PatchValue(&backups.BootstrapFunc, func(ctx environs.BootstrapContext, environ environs.Environ, args bootstrap.BootstrapParams) error {
   180  		return nil
   181  	})
   182  
   183  	_, err := testing.RunCommand(c, s.command, "restore", "-m", "testing:test1", "--file", "afile", "-b")
   184  	c.Assert(err, jc.ErrorIsNil)
   185  	c.Assert(s.store.Controllers["testing"], jc.DeepEquals, jujuclient.ControllerDetails{
   186  		CACert:                 testing.CACert,
   187  		ControllerUUID:         "deadbeef-0bad-400d-8000-4b1d0d06f00d",
   188  		APIEndpoints:           []string{"10.0.0.1:100"},
   189  		UnresolvedAPIEndpoints: []string{"10.0.0.1:100"},
   190  	})
   191  }
   192  
   193  type fakeInstance struct {
   194  	instance.Instance
   195  	id instance.Id
   196  }
   197  
   198  func (f fakeInstance) Addresses() ([]network.Address, error) {
   199  	return []network.Address{
   200  		{Value: "10.0.0.1"},
   201  	}, nil
   202  }
   203  
   204  type fakeEnviron struct {
   205  	environs.Environ
   206  	controllerInstances []instance.Id
   207  }
   208  
   209  func (f fakeEnviron) ControllerInstances() ([]instance.Id, error) {
   210  	return f.controllerInstances, nil
   211  }
   212  
   213  func (f fakeEnviron) Instances(ids []instance.Id) ([]instance.Instance, error) {
   214  	return []instance.Instance{fakeInstance{id: "1"}}, nil
   215  }
   216  
   217  func (f fakeEnviron) AllInstances() ([]instance.Instance, error) {
   218  	return []instance.Instance{fakeInstance{id: "1"}}, nil
   219  }
   220  
   221  func (f fakeEnviron) Config() *config.Config {
   222  	attrs := testing.FakeConfig().Merge(map[string]interface{}{"api-port": "100"})
   223  	cfg, _ := config.New(config.NoDefaults, attrs)
   224  	return cfg
   225  }