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  }