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  }