github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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 "io/ioutil" 8 "os" 9 "path/filepath" 10 "regexp" 11 12 jujutesting "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 "github.com/juju/juju/worker/uniter/charm" 24 ) 25 26 type BundlesDirSuite struct { 27 testing.JujuConnSuite 28 29 st api.Connection 30 uniter *uniter.State 31 } 32 33 var _ = gc.Suite(&BundlesDirSuite{}) 34 35 func (s *BundlesDirSuite) SetUpSuite(c *gc.C) { 36 s.JujuConnSuite.SetUpSuite(c) 37 } 38 39 func (s *BundlesDirSuite) TearDownSuite(c *gc.C) { 40 s.JujuConnSuite.TearDownSuite(c) 41 } 42 43 func (s *BundlesDirSuite) SetUpTest(c *gc.C) { 44 s.JujuConnSuite.SetUpTest(c) 45 46 // Add a charm, service and unit to login to the API with. 47 charm := s.AddTestingCharm(c, "wordpress") 48 service := s.AddTestingService(c, "wordpress", charm) 49 unit, err := service.AddUnit() 50 c.Assert(err, jc.ErrorIsNil) 51 password, err := utils.RandomPassword() 52 c.Assert(err, jc.ErrorIsNil) 53 err = unit.SetPassword(password) 54 c.Assert(err, jc.ErrorIsNil) 55 56 s.st = s.OpenAPIAs(c, unit.Tag(), password) 57 c.Assert(s.st, gc.NotNil) 58 s.uniter, err = s.st.Uniter() 59 c.Assert(err, jc.ErrorIsNil) 60 c.Assert(s.uniter, gc.NotNil) 61 } 62 63 func (s *BundlesDirSuite) TearDownTest(c *gc.C) { 64 err := s.st.Close() 65 c.Assert(err, jc.ErrorIsNil) 66 s.JujuConnSuite.TearDownTest(c) 67 } 68 69 func (s *BundlesDirSuite) AddCharm(c *gc.C) (charm.BundleInfo, *state.Charm) { 70 curl := corecharm.MustParseURL("cs:quantal/dummy-1") 71 bun := testcharms.Repo.CharmDir("dummy") 72 sch, err := testing.AddCharm(s.State, curl, bun) 73 c.Assert(err, jc.ErrorIsNil) 74 75 apiCharm, err := s.uniter.Charm(sch.URL()) 76 c.Assert(err, jc.ErrorIsNil) 77 78 return apiCharm, sch 79 } 80 81 type fakeBundleInfo struct { 82 charm.BundleInfo 83 curl *corecharm.URL 84 sha256 string 85 } 86 87 func (f fakeBundleInfo) URL() *corecharm.URL { 88 if f.curl == nil { 89 return f.BundleInfo.URL() 90 } 91 return f.curl 92 } 93 94 func (f fakeBundleInfo) ArchiveSha256() (string, error) { 95 if f.sha256 == "" { 96 return f.BundleInfo.ArchiveSha256() 97 } 98 return f.sha256, nil 99 } 100 101 func (s *BundlesDirSuite) TestGet(c *gc.C) { 102 basedir := c.MkDir() 103 bunsDir := filepath.Join(basedir, "random", "bundles") 104 downloader := api.NewCharmDownloader(s.st.Client()) 105 d := charm.NewBundlesDir(bunsDir, downloader) 106 107 checkDownloadsEmpty := func() { 108 files, err := ioutil.ReadDir(filepath.Join(bunsDir, "downloads")) 109 c.Assert(err, jc.ErrorIsNil) 110 c.Check(files, gc.HasLen, 0) 111 } 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.Check(err, gc.ErrorMatches, regexp.QuoteMeta(`failed to download charm "cs:quantal/dummy-1" from API server: `)+`expected sha256 "...", got ".*"`) 123 checkDownloadsEmpty() 124 125 // Try to get a charm whose bundle doesn't exist. 126 otherURL := corecharm.MustParseURL("cs:quantal/spam-1") 127 _, err = d.Read(&fakeBundleInfo{apiCharm, otherURL, ""}, nil) 128 c.Check(err, gc.ErrorMatches, regexp.QuoteMeta(`failed to download charm "cs:quantal/spam-1" from API server: `)+`.* not found`) 129 checkDownloadsEmpty() 130 131 // Get a charm whose bundle exists and whose content matches. 132 ch, err := d.Read(apiCharm, nil) 133 c.Assert(err, jc.ErrorIsNil) 134 assertCharm(c, ch, sch) 135 checkDownloadsEmpty() 136 137 // Get the same charm again, without preparing a response from the server. 138 ch, err = d.Read(apiCharm, nil) 139 c.Assert(err, jc.ErrorIsNil) 140 assertCharm(c, ch, sch) 141 checkDownloadsEmpty() 142 143 // Check the abort chan is honoured. 144 err = os.RemoveAll(bunsDir) 145 c.Assert(err, jc.ErrorIsNil) 146 abort := make(chan struct{}) 147 close(abort) 148 149 ch, err = d.Read(apiCharm, abort) 150 c.Check(ch, gc.IsNil) 151 c.Check(err, gc.ErrorMatches, regexp.QuoteMeta(`failed to download charm "cs:quantal/dummy-1" from API server: download aborted`)) 152 checkDownloadsEmpty() 153 } 154 155 func assertCharm(c *gc.C, bun charm.Bundle, sch *state.Charm) { 156 actual := bun.(*corecharm.CharmArchive) 157 c.Assert(actual.Revision(), gc.Equals, sch.Revision()) 158 c.Assert(actual.Meta(), gc.DeepEquals, sch.Meta()) 159 c.Assert(actual.Config(), gc.DeepEquals, sch.Config()) 160 } 161 162 type ClearDownloadsSuite struct { 163 jujutesting.IsolationSuite 164 } 165 166 var _ = gc.Suite(&ClearDownloadsSuite{}) 167 168 func (s *ClearDownloadsSuite) TestWorks(c *gc.C) { 169 baseDir := c.MkDir() 170 bunsDir := filepath.Join(baseDir, "bundles") 171 downloadDir := filepath.Join(bunsDir, "downloads") 172 c.Assert(os.MkdirAll(downloadDir, 0777), jc.ErrorIsNil) 173 c.Assert(ioutil.WriteFile(filepath.Join(downloadDir, "stuff"), []byte("foo"), 0755), jc.ErrorIsNil) 174 c.Assert(ioutil.WriteFile(filepath.Join(downloadDir, "thing"), []byte("bar"), 0755), jc.ErrorIsNil) 175 176 err := charm.ClearDownloads(bunsDir) 177 c.Assert(err, jc.ErrorIsNil) 178 checkMissing(c, downloadDir) 179 } 180 181 func (s *ClearDownloadsSuite) TestEmptyOK(c *gc.C) { 182 baseDir := c.MkDir() 183 bunsDir := filepath.Join(baseDir, "bundles") 184 downloadDir := filepath.Join(bunsDir, "downloads") 185 c.Assert(os.MkdirAll(downloadDir, 0777), jc.ErrorIsNil) 186 187 err := charm.ClearDownloads(bunsDir) 188 c.Assert(err, jc.ErrorIsNil) 189 checkMissing(c, downloadDir) 190 } 191 192 func (s *ClearDownloadsSuite) TestMissingOK(c *gc.C) { 193 baseDir := c.MkDir() 194 bunsDir := filepath.Join(baseDir, "bundles") 195 196 err := charm.ClearDownloads(bunsDir) 197 c.Assert(err, jc.ErrorIsNil) 198 } 199 200 func checkMissing(c *gc.C, p string) { 201 _, err := os.Stat(p) 202 if !os.IsNotExist(err) { 203 c.Fatalf("checking %s is missing: %v", p, err) 204 } 205 }