github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/commands/synctools_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package commands 5 6 import ( 7 "io" 8 "io/ioutil" 9 10 "github.com/juju/cmd" 11 "github.com/juju/errors" 12 "github.com/juju/loggo" 13 jc "github.com/juju/testing/checkers" 14 "github.com/juju/utils" 15 "github.com/juju/utils/arch" 16 "github.com/juju/utils/series" 17 "github.com/juju/version" 18 gc "gopkg.in/check.v1" 19 20 "github.com/juju/juju/apiserver/common" 21 "github.com/juju/juju/apiserver/params" 22 "github.com/juju/juju/cmd/modelcmd" 23 "github.com/juju/juju/environs/sync" 24 envtools "github.com/juju/juju/environs/tools" 25 "github.com/juju/juju/jujuclient" 26 "github.com/juju/juju/jujuclient/jujuclienttesting" 27 coretesting "github.com/juju/juju/testing" 28 coretools "github.com/juju/juju/tools" 29 jujuversion "github.com/juju/juju/version" 30 ) 31 32 type syncToolsSuite struct { 33 coretesting.FakeJujuXDGDataHomeSuite 34 fakeSyncToolsAPI *fakeSyncToolsAPI 35 store *jujuclienttesting.MemStore 36 } 37 38 var _ = gc.Suite(&syncToolsSuite{}) 39 40 func (s *syncToolsSuite) SetUpTest(c *gc.C) { 41 s.FakeJujuXDGDataHomeSuite.SetUpTest(c) 42 s.fakeSyncToolsAPI = &fakeSyncToolsAPI{} 43 s.PatchValue(&getSyncToolsAPI, func(c *syncToolsCommand) (syncToolsAPI, error) { 44 return s.fakeSyncToolsAPI, nil 45 }) 46 s.store = jujuclienttesting.NewMemStore() 47 s.store.CurrentControllerName = "ctrl" 48 s.store.Accounts["ctrl"] = jujuclient.AccountDetails{ 49 User: "admin@local", 50 } 51 } 52 53 func (s *syncToolsSuite) Reset(c *gc.C) { 54 s.TearDownTest(c) 55 s.SetUpTest(c) 56 } 57 58 func (s *syncToolsSuite) runSyncToolsCommand(c *gc.C, args ...string) (*cmd.Context, error) { 59 cmd := &syncToolsCommand{} 60 cmd.SetClientStore(s.store) 61 return coretesting.RunCommand(c, modelcmd.Wrap(cmd), args...) 62 } 63 64 var syncToolsCommandTests = []struct { 65 description string 66 args []string 67 sctx *sync.SyncContext 68 public bool 69 }{ 70 { 71 description: "model as only argument", 72 args: []string{"-m", "test-target"}, 73 sctx: &sync.SyncContext{}, 74 }, 75 { 76 description: "specifying also the synchronization source", 77 args: []string{"-m", "test-target", "--source", "/foo/bar"}, 78 sctx: &sync.SyncContext{ 79 Source: "/foo/bar", 80 }, 81 }, 82 { 83 description: "synchronize all version including development", 84 args: []string{"-m", "test-target", "--all", "--dev"}, 85 sctx: &sync.SyncContext{ 86 AllVersions: true, 87 Stream: "testing", 88 }, 89 }, 90 { 91 description: "just make a dry run", 92 args: []string{"-m", "test-target", "--dry-run"}, 93 sctx: &sync.SyncContext{ 94 DryRun: true, 95 }, 96 }, 97 { 98 description: "specified public (ignored by API)", 99 args: []string{"-m", "test-target", "--public"}, 100 sctx: &sync.SyncContext{}, 101 }, 102 { 103 description: "specify version", 104 args: []string{"-m", "test-target", "--version", "1.2"}, 105 sctx: &sync.SyncContext{ 106 MajorVersion: 1, 107 MinorVersion: 2, 108 }, 109 }, 110 } 111 112 func (s *syncToolsSuite) TestSyncToolsCommand(c *gc.C) { 113 for i, test := range syncToolsCommandTests { 114 c.Logf("test %d: %s", i, test.description) 115 called := false 116 syncTools = func(sctx *sync.SyncContext) error { 117 c.Assert(sctx.AllVersions, gc.Equals, test.sctx.AllVersions) 118 c.Assert(sctx.MajorVersion, gc.Equals, test.sctx.MajorVersion) 119 c.Assert(sctx.MinorVersion, gc.Equals, test.sctx.MinorVersion) 120 c.Assert(sctx.DryRun, gc.Equals, test.sctx.DryRun) 121 c.Assert(sctx.Stream, gc.Equals, test.sctx.Stream) 122 c.Assert(sctx.Source, gc.Equals, test.sctx.Source) 123 124 c.Assert(sctx.TargetToolsFinder, gc.FitsTypeOf, syncToolsAPIAdapter{}) 125 finder := sctx.TargetToolsFinder.(syncToolsAPIAdapter) 126 c.Assert(finder.syncToolsAPI, gc.Equals, s.fakeSyncToolsAPI) 127 128 c.Assert(sctx.TargetToolsUploader, gc.FitsTypeOf, syncToolsAPIAdapter{}) 129 uploader := sctx.TargetToolsUploader.(syncToolsAPIAdapter) 130 c.Assert(uploader.syncToolsAPI, gc.Equals, s.fakeSyncToolsAPI) 131 132 called = true 133 return nil 134 } 135 ctx, err := s.runSyncToolsCommand(c, test.args...) 136 c.Assert(err, jc.ErrorIsNil) 137 c.Assert(ctx, gc.NotNil) 138 c.Assert(called, jc.IsTrue) 139 s.Reset(c) 140 } 141 } 142 143 func (s *syncToolsSuite) TestSyncToolsCommandTargetDirectory(c *gc.C) { 144 called := false 145 dir := c.MkDir() 146 syncTools = func(sctx *sync.SyncContext) error { 147 c.Assert(sctx.AllVersions, jc.IsFalse) 148 c.Assert(sctx.DryRun, jc.IsFalse) 149 c.Assert(sctx.Stream, gc.Equals, "proposed") 150 c.Assert(sctx.Source, gc.Equals, "") 151 c.Assert(sctx.TargetToolsUploader, gc.FitsTypeOf, sync.StorageToolsUploader{}) 152 uploader := sctx.TargetToolsUploader.(sync.StorageToolsUploader) 153 c.Assert(uploader.WriteMirrors, gc.Equals, envtools.DoNotWriteMirrors) 154 url, err := uploader.Storage.URL("") 155 c.Assert(err, jc.ErrorIsNil) 156 c.Assert(url, gc.Equals, utils.MakeFileURL(dir)) 157 called = true 158 return nil 159 } 160 ctx, err := s.runSyncToolsCommand(c, "-m", "test-target", "--local-dir", dir, "--stream", "proposed") 161 c.Assert(err, jc.ErrorIsNil) 162 c.Assert(ctx, gc.NotNil) 163 c.Assert(called, jc.IsTrue) 164 } 165 166 func (s *syncToolsSuite) TestSyncToolsCommandTargetDirectoryPublic(c *gc.C) { 167 called := false 168 dir := c.MkDir() 169 syncTools = func(sctx *sync.SyncContext) error { 170 c.Assert(sctx.TargetToolsUploader, gc.FitsTypeOf, sync.StorageToolsUploader{}) 171 uploader := sctx.TargetToolsUploader.(sync.StorageToolsUploader) 172 c.Assert(uploader.WriteMirrors, gc.Equals, envtools.WriteMirrors) 173 called = true 174 return nil 175 } 176 ctx, err := s.runSyncToolsCommand(c, "-m", "test-target", "--local-dir", dir, "--public") 177 c.Assert(err, jc.ErrorIsNil) 178 c.Assert(ctx, gc.NotNil) 179 c.Assert(called, jc.IsTrue) 180 } 181 182 func (s *syncToolsSuite) TestSyncToolsCommandDeprecatedDestination(c *gc.C) { 183 called := false 184 dir := c.MkDir() 185 syncTools = func(sctx *sync.SyncContext) error { 186 c.Assert(sctx.AllVersions, jc.IsFalse) 187 c.Assert(sctx.DryRun, jc.IsFalse) 188 c.Assert(sctx.Stream, gc.Equals, "released") 189 c.Assert(sctx.Source, gc.Equals, "") 190 c.Assert(sctx.TargetToolsUploader, gc.FitsTypeOf, sync.StorageToolsUploader{}) 191 uploader := sctx.TargetToolsUploader.(sync.StorageToolsUploader) 192 url, err := uploader.Storage.URL("") 193 c.Assert(err, jc.ErrorIsNil) 194 c.Assert(url, gc.Equals, utils.MakeFileURL(dir)) 195 called = true 196 return nil 197 } 198 // Register writer. 199 var tw loggo.TestWriter 200 c.Assert(loggo.RegisterWriter("deprecated-tester", &tw), gc.IsNil) 201 defer loggo.RemoveWriter("deprecated-tester") 202 // Add deprecated message to be checked. 203 messages := []jc.SimpleMessage{ 204 {loggo.INFO, "Use of the --destination flag is deprecated in 1.18. Please use --local-dir instead."}, 205 } 206 // Run sync-tools command with --destination flag. 207 ctx, err := s.runSyncToolsCommand(c, "-m", "test-target", "--destination", dir, "--stream", "released") 208 c.Assert(err, jc.ErrorIsNil) 209 c.Assert(ctx, gc.NotNil) 210 c.Assert(called, jc.IsTrue) 211 // Check deprecated message was logged. 212 c.Check(tw.Log(), jc.LogMatches, messages) 213 } 214 215 func (s *syncToolsSuite) TestAPIAdapterFindTools(c *gc.C) { 216 var called bool 217 result := coretools.List{&coretools.Tools{}} 218 fake := fakeSyncToolsAPI{ 219 findTools: func(majorVersion, minorVersion int, series, arch string) (params.FindToolsResult, error) { 220 called = true 221 c.Assert(majorVersion, gc.Equals, 2) 222 c.Assert(minorVersion, gc.Equals, -1) 223 c.Assert(series, gc.Equals, "") 224 c.Assert(arch, gc.Equals, "") 225 return params.FindToolsResult{List: result}, nil 226 }, 227 } 228 a := syncToolsAPIAdapter{&fake} 229 list, err := a.FindTools(2, "released") 230 c.Assert(err, jc.ErrorIsNil) 231 c.Assert(list, jc.SameContents, result) 232 c.Assert(called, jc.IsTrue) 233 } 234 235 func (s *syncToolsSuite) TestAPIAdapterFindToolsNotFound(c *gc.C) { 236 fake := fakeSyncToolsAPI{ 237 findTools: func(majorVersion, minorVersion int, series, arch string) (params.FindToolsResult, error) { 238 err := common.ServerError(errors.NotFoundf("tools")) 239 return params.FindToolsResult{Error: err}, nil 240 }, 241 } 242 a := syncToolsAPIAdapter{&fake} 243 list, err := a.FindTools(1, "released") 244 c.Assert(err, gc.Equals, coretools.ErrNoMatches) 245 c.Assert(list, gc.HasLen, 0) 246 } 247 248 func (s *syncToolsSuite) TestAPIAdapterFindToolsAPIError(c *gc.C) { 249 findToolsErr := common.ServerError(errors.NotFoundf("tools")) 250 fake := fakeSyncToolsAPI{ 251 findTools: func(majorVersion, minorVersion int, series, arch string) (params.FindToolsResult, error) { 252 return params.FindToolsResult{Error: findToolsErr}, findToolsErr 253 }, 254 } 255 a := syncToolsAPIAdapter{&fake} 256 list, err := a.FindTools(1, "released") 257 c.Assert(err, gc.Equals, findToolsErr) // error comes through untranslated 258 c.Assert(list, gc.HasLen, 0) 259 } 260 261 func (s *syncToolsSuite) TestAPIAdapterUploadTools(c *gc.C) { 262 uploadToolsErr := errors.New("uh oh") 263 current := version.Binary{ 264 Number: jujuversion.Current, 265 Arch: arch.HostArch(), 266 Series: series.HostSeries(), 267 } 268 fake := fakeSyncToolsAPI{ 269 uploadTools: func(r io.Reader, v version.Binary, additionalSeries ...string) (coretools.List, error) { 270 data, err := ioutil.ReadAll(r) 271 c.Assert(err, jc.ErrorIsNil) 272 c.Assert(string(data), gc.Equals, "abc") 273 c.Assert(v, gc.Equals, current) 274 return nil, uploadToolsErr 275 }, 276 } 277 a := syncToolsAPIAdapter{&fake} 278 err := a.UploadTools("released", "released", &coretools.Tools{Version: current}, []byte("abc")) 279 c.Assert(err, gc.Equals, uploadToolsErr) 280 } 281 282 func (s *syncToolsSuite) TestAPIAdapterBlockUploadTools(c *gc.C) { 283 syncTools = func(sctx *sync.SyncContext) error { 284 // Block operation 285 return common.OperationBlockedError("TestAPIAdapterBlockUploadTools") 286 } 287 _, err := s.runSyncToolsCommand(c, "-m", "test-target", "--destination", c.MkDir(), "--stream", "released") 288 coretesting.AssertOperationWasBlocked(c, err, ".*TestAPIAdapterBlockUploadTools.*") 289 } 290 291 type fakeSyncToolsAPI struct { 292 findTools func(majorVersion, minorVersion int, series, arch string) (params.FindToolsResult, error) 293 uploadTools func(r io.Reader, v version.Binary, additionalSeries ...string) (coretools.List, error) 294 } 295 296 func (f *fakeSyncToolsAPI) FindTools(majorVersion, minorVersion int, series, arch string) (params.FindToolsResult, error) { 297 return f.findTools(majorVersion, minorVersion, series, arch) 298 } 299 300 func (f *fakeSyncToolsAPI) UploadTools(r io.ReadSeeker, v version.Binary, additionalSeries ...string) (coretools.List, error) { 301 return f.uploadTools(r, v, additionalSeries...) 302 } 303 304 func (f *fakeSyncToolsAPI) Close() error { 305 return nil 306 }