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