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