github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/controller/charmrevisionupdater/updater_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package charmrevisionupdater_test
     5  
     6  import (
     7  	"net/http"
     8  	"net/http/httptest"
     9  
    10  	"github.com/juju/errors"
    11  	jc "github.com/juju/testing/checkers"
    12  	gc "gopkg.in/check.v1"
    13  	"gopkg.in/juju/charm.v6"
    14  	"gopkg.in/juju/charmrepo.v3"
    15  	"gopkg.in/juju/names.v2"
    16  
    17  	"github.com/juju/juju/apiserver/common"
    18  	"github.com/juju/juju/apiserver/facades/controller/charmrevisionupdater"
    19  	"github.com/juju/juju/apiserver/facades/controller/charmrevisionupdater/testing"
    20  	apiservertesting "github.com/juju/juju/apiserver/testing"
    21  	"github.com/juju/juju/charmstore"
    22  	jujutesting "github.com/juju/juju/juju/testing"
    23  	"github.com/juju/juju/state"
    24  	"github.com/juju/juju/version"
    25  )
    26  
    27  type charmVersionSuite struct {
    28  	testing.CharmSuite
    29  	jujutesting.JujuConnSuite
    30  
    31  	charmrevisionupdater *charmrevisionupdater.CharmRevisionUpdaterAPI
    32  	resources            *common.Resources
    33  	authoriser           apiservertesting.FakeAuthorizer
    34  }
    35  
    36  var _ = gc.Suite(&charmVersionSuite{})
    37  
    38  func (s *charmVersionSuite) SetUpSuite(c *gc.C) {
    39  	s.JujuConnSuite.SetUpSuite(c)
    40  	s.CharmSuite.SetUpSuite(c, &s.JujuConnSuite)
    41  }
    42  
    43  func (s *charmVersionSuite) TearDownSuite(c *gc.C) {
    44  	s.CharmSuite.TearDownSuite(c)
    45  	s.JujuConnSuite.TearDownSuite(c)
    46  }
    47  
    48  func (s *charmVersionSuite) SetUpTest(c *gc.C) {
    49  	s.JujuConnSuite.SetUpTest(c)
    50  	s.CharmSuite.SetUpTest(c)
    51  	s.resources = common.NewResources()
    52  	s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() })
    53  	s.authoriser = apiservertesting.FakeAuthorizer{
    54  		Controller: true,
    55  		Tag:        names.NewMachineTag("99"),
    56  	}
    57  	var err error
    58  	s.charmrevisionupdater, err = charmrevisionupdater.NewCharmRevisionUpdaterAPI(s.State, s.resources, s.authoriser)
    59  	c.Assert(err, jc.ErrorIsNil)
    60  }
    61  
    62  func (s *charmVersionSuite) TearDownTest(c *gc.C) {
    63  	s.CharmSuite.TearDownTest(c)
    64  	s.JujuConnSuite.TearDownTest(c)
    65  }
    66  
    67  func (s *charmVersionSuite) TestNewCharmRevisionUpdaterAPIAcceptsStateManager(c *gc.C) {
    68  	endPoint, err := charmrevisionupdater.NewCharmRevisionUpdaterAPI(s.State, s.resources, s.authoriser)
    69  	c.Assert(err, jc.ErrorIsNil)
    70  	c.Assert(endPoint, gc.NotNil)
    71  }
    72  
    73  func (s *charmVersionSuite) TestNewCharmRevisionUpdaterAPIRefusesNonStateManager(c *gc.C) {
    74  	anAuthoriser := s.authoriser
    75  	anAuthoriser.Controller = false
    76  	endPoint, err := charmrevisionupdater.NewCharmRevisionUpdaterAPI(s.State, s.resources, anAuthoriser)
    77  	c.Assert(endPoint, gc.IsNil)
    78  	c.Assert(err, gc.ErrorMatches, "permission denied")
    79  }
    80  
    81  func (s *charmVersionSuite) TestUpdateRevisions(c *gc.C) {
    82  	s.AddMachine(c, "0", state.JobManageModel)
    83  	s.SetupScenario(c)
    84  
    85  	curl := charm.MustParseURL("cs:quantal/mysql")
    86  	_, err := s.State.LatestPlaceholderCharm(curl)
    87  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
    88  
    89  	curl = charm.MustParseURL("cs:quantal/wordpress")
    90  	_, err = s.State.LatestPlaceholderCharm(curl)
    91  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
    92  
    93  	result, err := s.charmrevisionupdater.UpdateLatestRevisions()
    94  	c.Assert(err, jc.ErrorIsNil)
    95  	c.Assert(result.Error, gc.IsNil)
    96  
    97  	curl = charm.MustParseURL("cs:quantal/mysql")
    98  	pending, err := s.State.LatestPlaceholderCharm(curl)
    99  	c.Assert(err, jc.ErrorIsNil)
   100  	c.Assert(pending.String(), gc.Equals, "cs:quantal/mysql-23")
   101  
   102  	// Latest wordpress is already deployed, so no pending charm.
   103  	curl = charm.MustParseURL("cs:quantal/wordpress")
   104  	_, err = s.State.LatestPlaceholderCharm(curl)
   105  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   106  
   107  	// Varnish has an error when updating, so no pending charm.
   108  	curl = charm.MustParseURL("cs:quantal/varnish")
   109  	_, err = s.State.LatestPlaceholderCharm(curl)
   110  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   111  
   112  	// Update mysql version and run update again.
   113  	app, err := s.State.Application("mysql")
   114  	c.Assert(err, jc.ErrorIsNil)
   115  	ch := s.AddCharmWithRevision(c, "mysql", 23)
   116  	cfg := state.SetCharmConfig{
   117  		Charm:      ch,
   118  		ForceUnits: true,
   119  	}
   120  	err = app.SetCharm(cfg)
   121  	c.Assert(err, jc.ErrorIsNil)
   122  
   123  	result, err = s.charmrevisionupdater.UpdateLatestRevisions()
   124  	c.Assert(err, jc.ErrorIsNil)
   125  	c.Assert(result.Error, gc.IsNil)
   126  
   127  	// Latest mysql is now deployed, so no pending charm.
   128  	curl = charm.MustParseURL("cs:quantal/mysql")
   129  	_, err = s.State.LatestPlaceholderCharm(curl)
   130  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   131  }
   132  
   133  func (s *charmVersionSuite) TestWordpressCharmNoReadAccessIsNotVisible(c *gc.C) {
   134  	s.AddMachine(c, "0", state.JobManageModel)
   135  	s.SetupScenario(c)
   136  
   137  	// Disallow read access to the wordpress charm in the charm store.
   138  	err := s.Client.Put("/quantal/wordpress/meta/perm/read", nil)
   139  	c.Assert(err, jc.ErrorIsNil)
   140  
   141  	// Run the revision updater and check that the public charm updates are
   142  	// still properly notified.
   143  	result, err := s.charmrevisionupdater.UpdateLatestRevisions()
   144  	c.Assert(err, jc.ErrorIsNil)
   145  	c.Assert(result.Error, gc.IsNil)
   146  
   147  	curl := charm.MustParseURL("cs:quantal/mysql")
   148  	pending, err := s.State.LatestPlaceholderCharm(curl)
   149  	c.Assert(err, jc.ErrorIsNil)
   150  	c.Assert(pending.String(), gc.Equals, "cs:quantal/mysql-23")
   151  
   152  	// No pending charm for wordpress.
   153  	curl = charm.MustParseURL("cs:quantal/wordpress")
   154  	_, err = s.State.LatestPlaceholderCharm(curl)
   155  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   156  }
   157  
   158  func (s *charmVersionSuite) TestJujuMetadataHeaderIsSent(c *gc.C) {
   159  	s.AddMachine(c, "0", state.JobManageModel)
   160  	s.SetupScenario(c)
   161  
   162  	// Set up a charm store server that stores the request header.
   163  	var header http.Header
   164  	received := false
   165  	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   166  		// the first request is the one with the UUID.
   167  		if !received {
   168  			header = r.Header
   169  			received = true
   170  		}
   171  		s.Handler.ServeHTTP(w, r)
   172  	}))
   173  	defer srv.Close()
   174  
   175  	// Point the charm repo initializer to the testing server.
   176  	s.PatchValue(&charmrevisionupdater.NewCharmStoreClient, func(st *state.State) (charmstore.Client, error) {
   177  		return charmstore.NewCachingClient(state.MacaroonCache{st}, srv.URL)
   178  	})
   179  
   180  	result, err := s.charmrevisionupdater.UpdateLatestRevisions()
   181  	c.Assert(err, jc.ErrorIsNil)
   182  	c.Assert(result.Error, gc.IsNil)
   183  
   184  	model, err := s.State.Model()
   185  	c.Assert(err, jc.ErrorIsNil)
   186  	cloud, err := s.State.Cloud(model.Cloud())
   187  	c.Assert(err, jc.ErrorIsNil)
   188  	expectedHeader := []string{
   189  		"arch=amd64", // This is the architecture of the deployed applications.
   190  		"cloud=" + model.Cloud(),
   191  		"cloud_region=" + model.CloudRegion(),
   192  		"controller_uuid=" + s.State.ControllerUUID(),
   193  		"controller_version=" + version.Current.String(),
   194  		"environment_uuid=" + model.UUID(),
   195  		"is_controller=true",
   196  		"model_uuid=" + model.UUID(),
   197  		"provider=" + cloud.Type,
   198  		"series=quantal",
   199  	}
   200  	for i, expected := range expectedHeader {
   201  		c.Assert(header[charmrepo.JujuMetadataHTTPHeader][i], gc.Equals, expected)
   202  	}
   203  }