github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/migration/migration_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package migration_test 5 6 import ( 7 "bytes" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "net/url" 12 13 "github.com/juju/errors" 14 jc "github.com/juju/testing/checkers" 15 "github.com/juju/utils" 16 "github.com/juju/version" 17 gc "gopkg.in/check.v1" 18 "gopkg.in/juju/charm.v6-unstable" 19 20 "github.com/juju/juju/core/description" 21 "github.com/juju/juju/migration" 22 "github.com/juju/juju/provider/dummy" 23 _ "github.com/juju/juju/provider/dummy" 24 statetesting "github.com/juju/juju/state/testing" 25 "github.com/juju/juju/testing" 26 "github.com/juju/juju/tools" 27 ) 28 29 type ImportSuite struct { 30 statetesting.StateSuite 31 } 32 33 var _ = gc.Suite(&ImportSuite{}) 34 35 func (s *ImportSuite) SetUpTest(c *gc.C) { 36 // Specify the config to use for the controller model before calling 37 // SetUpTest of the StateSuite, otherwise we get testing.ModelConfig(c). 38 // The default provider type specified in the testing.ModelConfig function 39 // is one that isn't registered as a valid provider. For our tests here we 40 // need a real registered provider, so we use the dummy provider. 41 // NOTE: make a better test provider. 42 s.InitialConfig = testing.CustomModelConfig(c, dummy.SampleConfig()) 43 s.StateSuite.SetUpTest(c) 44 } 45 46 func (s *ImportSuite) TestBadBytes(c *gc.C) { 47 bytes := []byte("not a model") 48 model, st, err := migration.ImportModel(s.State, bytes) 49 c.Check(st, gc.IsNil) 50 c.Check(model, gc.IsNil) 51 c.Assert(err, gc.ErrorMatches, "yaml: unmarshal errors:\n.*") 52 } 53 54 func (s *ImportSuite) TestImportModel(c *gc.C) { 55 model, err := s.State.Export() 56 c.Check(err, jc.ErrorIsNil) 57 58 // Update the config values in the exported model for different values for 59 // "state-port", "api-port", and "ca-cert". Also give the model a new UUID 60 // and name so we can import it nicely. 61 uuid := utils.MustNewUUID().String() 62 model.UpdateConfig(map[string]interface{}{ 63 "name": "new-model", 64 "uuid": uuid, 65 }) 66 67 bytes, err := description.Serialize(model) 68 c.Check(err, jc.ErrorIsNil) 69 70 dbModel, dbState, err := migration.ImportModel(s.State, bytes) 71 c.Check(err, jc.ErrorIsNil) 72 defer dbState.Close() 73 74 dbConfig, err := dbModel.Config() 75 c.Assert(err, jc.ErrorIsNil) 76 c.Assert(dbConfig.UUID(), gc.Equals, uuid) 77 c.Assert(dbConfig.Name(), gc.Equals, "new-model") 78 } 79 80 func (s *ImportSuite) TestUploadBinariesConfigValidate(c *gc.C) { 81 type T migration.UploadBinariesConfig // alias for brevity 82 83 check := func(modify func(*T), missing string) { 84 config := T{ 85 CharmDownloader: struct{ migration.CharmDownloader }{}, 86 CharmUploader: struct{ migration.CharmUploader }{}, 87 ToolsDownloader: struct{ migration.ToolsDownloader }{}, 88 ToolsUploader: struct{ migration.ToolsUploader }{}, 89 } 90 modify(&config) 91 realConfig := migration.UploadBinariesConfig(config) 92 c.Check(realConfig.Validate(), gc.ErrorMatches, fmt.Sprintf("missing %s not valid", missing)) 93 } 94 95 check(func(c *T) { c.CharmDownloader = nil }, "CharmDownloader") 96 check(func(c *T) { c.CharmUploader = nil }, "CharmUploader") 97 check(func(c *T) { c.ToolsDownloader = nil }, "ToolsDownloader") 98 check(func(c *T) { c.ToolsUploader = nil }, "ToolsUploader") 99 } 100 101 func (s *ImportSuite) TestBinariesMigration(c *gc.C) { 102 downloader := &fakeDownloader{} 103 uploader := &fakeUploader{ 104 charms: make(map[string]string), 105 tools: make(map[version.Binary]string), 106 } 107 108 toolsMap := map[version.Binary]string{ 109 version.MustParseBinary("2.1.0-trusty-amd64"): "/tools/0", 110 version.MustParseBinary("2.0.0-xenial-amd64"): "/tools/1", 111 } 112 config := migration.UploadBinariesConfig{ 113 Charms: []string{"local:trusty/magic", "cs:trusty/postgresql-42"}, 114 CharmDownloader: downloader, 115 CharmUploader: uploader, 116 Tools: toolsMap, 117 ToolsDownloader: downloader, 118 ToolsUploader: uploader, 119 } 120 err := migration.UploadBinaries(config) 121 c.Assert(err, jc.ErrorIsNil) 122 123 c.Assert(downloader.charms, jc.DeepEquals, []string{ 124 "local:trusty/magic", 125 "cs:trusty/postgresql-42", 126 }) 127 c.Assert(uploader.charms, jc.DeepEquals, map[string]string{ 128 "local:trusty/magic": "local:trusty/magic content", 129 "cs:trusty/postgresql-42": "cs:trusty/postgresql-42 content", 130 }) 131 c.Assert(downloader.uris, jc.SameContents, []string{ 132 "/tools/0", 133 "/tools/1", 134 }) 135 c.Assert(uploader.tools, jc.DeepEquals, toolsMap) 136 } 137 138 type fakeDownloader struct { 139 charms []string 140 uris []string 141 } 142 143 func (d *fakeDownloader) OpenCharm(curl *charm.URL) (io.ReadCloser, error) { 144 urlStr := curl.String() 145 d.charms = append(d.charms, urlStr) 146 // Return the charm URL string as the fake charm content 147 return ioutil.NopCloser(bytes.NewReader([]byte(urlStr + " content"))), nil 148 } 149 150 func (d *fakeDownloader) OpenURI(uri string, query url.Values) (io.ReadCloser, error) { 151 if query != nil { 152 panic("query should be empty") 153 } 154 d.uris = append(d.uris, uri) 155 // Return the URI string as fake content 156 return ioutil.NopCloser(bytes.NewReader([]byte(uri))), nil 157 } 158 159 type fakeUploader struct { 160 tools map[version.Binary]string 161 charms map[string]string 162 } 163 164 func (f *fakeUploader) UploadTools(r io.ReadSeeker, v version.Binary, _ ...string) (tools.List, error) { 165 data, err := ioutil.ReadAll(r) 166 if err != nil { 167 return nil, errors.Trace(err) 168 } 169 f.tools[v] = string(data) 170 return tools.List{&tools.Tools{Version: v}}, nil 171 } 172 173 func (f *fakeUploader) UploadCharm(u *charm.URL, r io.ReadSeeker) (*charm.URL, error) { 174 data, err := ioutil.ReadAll(r) 175 if err != nil { 176 return nil, errors.Trace(err) 177 } 178 179 f.charms[u.String()] = string(data) 180 return u, nil 181 } 182 183 type ExportSuite struct { 184 statetesting.StateSuite 185 } 186 187 var _ = gc.Suite(&ExportSuite{}) 188 189 func (s *ExportSuite) TestExportModel(c *gc.C) { 190 bytes, err := migration.ExportModel(s.State) 191 c.Assert(err, jc.ErrorIsNil) 192 // The bytes must be a valid model. 193 _, err = description.Deserialize(bytes) 194 c.Assert(err, jc.ErrorIsNil) 195 }