github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/worker/uniter/charm/bundles_test.go (about) 1 // Copyright 2012-2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package charm_test 5 6 import ( 7 "os" 8 "path/filepath" 9 "regexp" 10 "time" 11 12 gitjujutesting "github.com/juju/testing" 13 jc "github.com/juju/testing/checkers" 14 "github.com/juju/utils" 15 gc "gopkg.in/check.v1" 16 corecharm "gopkg.in/juju/charm.v6-unstable" 17 18 "github.com/juju/juju/api" 19 "github.com/juju/juju/api/uniter" 20 "github.com/juju/juju/juju/testing" 21 "github.com/juju/juju/state" 22 "github.com/juju/juju/testcharms" 23 coretesting "github.com/juju/juju/testing" 24 "github.com/juju/juju/worker/uniter/charm" 25 ) 26 27 type BundlesDirSuite struct { 28 gitjujutesting.HTTPSuite 29 testing.JujuConnSuite 30 31 st api.Connection 32 uniter *uniter.State 33 } 34 35 var _ = gc.Suite(&BundlesDirSuite{}) 36 37 func (s *BundlesDirSuite) SetUpSuite(c *gc.C) { 38 s.HTTPSuite.SetUpSuite(c) 39 s.JujuConnSuite.SetUpSuite(c) 40 } 41 42 func (s *BundlesDirSuite) TearDownSuite(c *gc.C) { 43 s.JujuConnSuite.TearDownSuite(c) 44 s.HTTPSuite.TearDownSuite(c) 45 } 46 47 func (s *BundlesDirSuite) SetUpTest(c *gc.C) { 48 s.HTTPSuite.SetUpTest(c) 49 s.JujuConnSuite.SetUpTest(c) 50 51 // Add a charm, service and unit to login to the API with. 52 charm := s.AddTestingCharm(c, "wordpress") 53 service := s.AddTestingService(c, "wordpress", charm) 54 unit, err := service.AddUnit() 55 c.Assert(err, jc.ErrorIsNil) 56 password, err := utils.RandomPassword() 57 c.Assert(err, jc.ErrorIsNil) 58 err = unit.SetPassword(password) 59 c.Assert(err, jc.ErrorIsNil) 60 61 s.st = s.OpenAPIAs(c, unit.Tag(), password) 62 c.Assert(s.st, gc.NotNil) 63 s.uniter, err = s.st.Uniter() 64 c.Assert(err, jc.ErrorIsNil) 65 c.Assert(s.uniter, gc.NotNil) 66 } 67 68 func (s *BundlesDirSuite) TearDownTest(c *gc.C) { 69 err := s.st.Close() 70 c.Assert(err, jc.ErrorIsNil) 71 s.JujuConnSuite.TearDownTest(c) 72 s.HTTPSuite.TearDownTest(c) 73 } 74 75 func (s *BundlesDirSuite) AddCharm(c *gc.C) (charm.BundleInfo, *state.Charm) { 76 curl := corecharm.MustParseURL("cs:quantal/dummy-1") 77 bun := testcharms.Repo.CharmDir("dummy") 78 sch, err := testing.AddCharm(s.State, curl, bun) 79 c.Assert(err, jc.ErrorIsNil) 80 81 apiCharm, err := s.uniter.Charm(sch.URL()) 82 c.Assert(err, jc.ErrorIsNil) 83 84 return apiCharm, sch 85 } 86 87 type fakeBundleInfo struct { 88 charm.BundleInfo 89 curl *corecharm.URL 90 sha256 string 91 } 92 93 func (f fakeBundleInfo) URL() *corecharm.URL { 94 if f.curl == nil { 95 return f.BundleInfo.URL() 96 } 97 return f.curl 98 } 99 100 func (f fakeBundleInfo) ArchiveSha256() (string, error) { 101 if f.sha256 == "" { 102 return f.BundleInfo.ArchiveSha256() 103 } 104 return f.sha256, nil 105 } 106 107 func (s *BundlesDirSuite) TestGet(c *gc.C) { 108 basedir := c.MkDir() 109 bunsdir := filepath.Join(basedir, "random", "bundles") 110 downloader := api.NewCharmDownloader(s.st.Client()) 111 d := charm.NewBundlesDir(bunsdir, downloader) 112 113 // Check it doesn't get created until it's needed. 114 _, err := os.Stat(bunsdir) 115 c.Assert(err, jc.Satisfies, os.IsNotExist) 116 117 // Add a charm to state that we can try to get. 118 apiCharm, sch := s.AddCharm(c) 119 120 // Try to get the charm when the content doesn't match. 121 _, err = d.Read(&fakeBundleInfo{apiCharm, nil, "..."}, nil) 122 c.Assert(err, gc.ErrorMatches, regexp.QuoteMeta(`failed to download charm "cs:quantal/dummy-1" from API server: `)+`expected sha256 "...", got ".*"`) 123 124 // Try to get a charm whose bundle doesn't exist. 125 otherURL := corecharm.MustParseURL("cs:quantal/spam-1") 126 _, err = d.Read(&fakeBundleInfo{apiCharm, otherURL, ""}, nil) 127 c.Assert(err, gc.ErrorMatches, regexp.QuoteMeta(`failed to download charm "cs:quantal/spam-1" from API server: `)+`.* not found`) 128 129 // Get a charm whose bundle exists and whose content matches. 130 ch, err := d.Read(apiCharm, nil) 131 c.Assert(err, jc.ErrorIsNil) 132 assertCharm(c, ch, sch) 133 134 // Get the same charm again, without preparing a response from the server. 135 ch, err = d.Read(apiCharm, nil) 136 c.Assert(err, jc.ErrorIsNil) 137 assertCharm(c, ch, sch) 138 139 // Abort a download. 140 err = os.RemoveAll(bunsdir) 141 c.Assert(err, jc.ErrorIsNil) 142 abort := make(chan struct{}) 143 done := make(chan bool) 144 go func() { 145 ch, err := d.Read(apiCharm, abort) 146 c.Assert(ch, gc.IsNil) 147 c.Assert(err, gc.ErrorMatches, regexp.QuoteMeta(`failed to download charm "cs:quantal/dummy-1" from API server: aborted`)) 148 close(done) 149 }() 150 close(abort) 151 gitjujutesting.Server.Response(500, nil, nil) 152 select { 153 case <-done: 154 case <-time.After(coretesting.LongWait): 155 c.Fatalf("timed out waiting for abort") 156 } 157 } 158 159 func assertCharm(c *gc.C, bun charm.Bundle, sch *state.Charm) { 160 actual := bun.(*corecharm.CharmArchive) 161 c.Assert(actual.Revision(), gc.Equals, sch.Revision()) 162 c.Assert(actual.Meta(), gc.DeepEquals, sch.Meta()) 163 c.Assert(actual.Config(), gc.DeepEquals, sch.Config()) 164 }