github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/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 "crypto/sha256" 8 "encoding/hex" 9 "fmt" 10 "io/ioutil" 11 "net/url" 12 "os" 13 "path/filepath" 14 "time" 15 16 jc "github.com/juju/testing/checkers" 17 "github.com/juju/utils" 18 gc "launchpad.net/gocheck" 19 20 corecharm "github.com/juju/juju/charm" 21 charmtesting "github.com/juju/juju/charm/testing" 22 "github.com/juju/juju/juju/testing" 23 "github.com/juju/juju/state" 24 "github.com/juju/juju/state/api" 25 "github.com/juju/juju/state/api/uniter" 26 coretesting "github.com/juju/juju/testing" 27 "github.com/juju/juju/worker/uniter/charm" 28 ) 29 30 type BundlesDirSuite struct { 31 coretesting.HTTPSuite 32 testing.JujuConnSuite 33 34 st *api.State 35 uniter *uniter.State 36 } 37 38 var _ = gc.Suite(&BundlesDirSuite{}) 39 40 func (s *BundlesDirSuite) SetUpSuite(c *gc.C) { 41 s.HTTPSuite.SetUpSuite(c) 42 s.JujuConnSuite.SetUpSuite(c) 43 } 44 45 func (s *BundlesDirSuite) TearDownSuite(c *gc.C) { 46 s.JujuConnSuite.TearDownSuite(c) 47 s.HTTPSuite.TearDownSuite(c) 48 } 49 50 func (s *BundlesDirSuite) SetUpTest(c *gc.C) { 51 s.HTTPSuite.SetUpTest(c) 52 s.JujuConnSuite.SetUpTest(c) 53 54 // Add a charm, service and unit to login to the API with. 55 charm := s.AddTestingCharm(c, "wordpress") 56 service := s.AddTestingService(c, "wordpress", charm) 57 unit, err := service.AddUnit() 58 c.Assert(err, gc.IsNil) 59 password, err := utils.RandomPassword() 60 c.Assert(err, gc.IsNil) 61 err = unit.SetPassword(password) 62 c.Assert(err, gc.IsNil) 63 64 s.st = s.OpenAPIAs(c, unit.Tag(), password) 65 c.Assert(s.st, gc.NotNil) 66 s.uniter = s.st.Uniter() 67 c.Assert(s.uniter, gc.NotNil) 68 } 69 70 func (s *BundlesDirSuite) TearDownTest(c *gc.C) { 71 err := s.st.Close() 72 c.Assert(err, gc.IsNil) 73 s.JujuConnSuite.TearDownTest(c) 74 s.HTTPSuite.TearDownTest(c) 75 } 76 77 func (s *BundlesDirSuite) AddCharm(c *gc.C) (*uniter.Charm, *state.Charm, []byte) { 78 curl := corecharm.MustParseURL("cs:quantal/dummy-1") 79 surl, err := url.Parse(s.URL("/some/charm.bundle")) 80 c.Assert(err, gc.IsNil) 81 bunpath := charmtesting.Charms.BundlePath(c.MkDir(), "dummy") 82 bun, err := corecharm.ReadBundle(bunpath) 83 c.Assert(err, gc.IsNil) 84 bundata, hash := readHash(c, bunpath) 85 sch, err := s.State.AddCharm(bun, curl, surl, hash) 86 c.Assert(err, gc.IsNil) 87 apiCharm, err := s.uniter.Charm(sch.URL()) 88 c.Assert(err, gc.IsNil) 89 return apiCharm, sch, bundata 90 } 91 92 func (s *BundlesDirSuite) TestGet(c *gc.C) { 93 basedir := c.MkDir() 94 bunsdir := filepath.Join(basedir, "random", "bundles") 95 d := charm.NewBundlesDir(bunsdir) 96 97 // Check it doesn't get created until it's needed. 98 _, err := os.Stat(bunsdir) 99 c.Assert(err, jc.Satisfies, os.IsNotExist) 100 101 // Add a charm to state that we can try to get. 102 apiCharm, sch, bundata := s.AddCharm(c) 103 104 // Try to get the charm when the content doesn't match. 105 coretesting.Server.Response(200, nil, []byte("roflcopter")) 106 _, err = d.Read(apiCharm, nil) 107 prefix := fmt.Sprintf(`failed to download charm "cs:quantal/dummy-1" from %q: `, sch.BundleURL()) 108 c.Assert(err, gc.ErrorMatches, prefix+fmt.Sprintf(`expected sha256 %q, got ".*"`, sch.BundleSha256())) 109 110 // Try to get a charm whose bundle doesn't exist. 111 coretesting.Server.Response(404, nil, nil) 112 _, err = d.Read(apiCharm, nil) 113 c.Assert(err, gc.ErrorMatches, prefix+`.* 404 Not Found`) 114 115 // Get a charm whose bundle exists and whose content matches. 116 coretesting.Server.Response(200, nil, bundata) 117 ch, err := d.Read(apiCharm, nil) 118 c.Assert(err, gc.IsNil) 119 assertCharm(c, ch, sch) 120 121 // Get the same charm again, without preparing a response from the server. 122 ch, err = d.Read(apiCharm, nil) 123 c.Assert(err, gc.IsNil) 124 assertCharm(c, ch, sch) 125 126 // Abort a download. 127 err = os.RemoveAll(bunsdir) 128 c.Assert(err, gc.IsNil) 129 abort := make(chan struct{}) 130 done := make(chan bool) 131 go func() { 132 ch, err := d.Read(apiCharm, abort) 133 c.Assert(ch, gc.IsNil) 134 c.Assert(err, gc.ErrorMatches, prefix+"aborted") 135 close(done) 136 }() 137 close(abort) 138 coretesting.Server.Response(500, nil, nil) 139 select { 140 case <-done: 141 case <-time.After(coretesting.LongWait): 142 c.Fatalf("timed out waiting for abort") 143 } 144 } 145 146 func readHash(c *gc.C, path string) ([]byte, string) { 147 data, err := ioutil.ReadFile(path) 148 c.Assert(err, gc.IsNil) 149 hash := sha256.New() 150 hash.Write(data) 151 return data, hex.EncodeToString(hash.Sum(nil)) 152 } 153 154 func assertCharm(c *gc.C, bun charm.Bundle, sch *state.Charm) { 155 actual := bun.(*corecharm.Bundle) 156 c.Assert(actual.Revision(), gc.Equals, sch.Revision()) 157 c.Assert(actual.Meta(), gc.DeepEquals, sch.Meta()) 158 c.Assert(actual.Config(), gc.DeepEquals, sch.Config()) 159 }