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{}, ¶ms.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{}, ¶ms.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 }