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