github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/featuretests/client_macaroon_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package featuretests
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  
    10  	"github.com/juju/charm/v12"
    11  	jc "github.com/juju/testing/checkers"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/api/client/charms"
    15  	apitesting "github.com/juju/juju/api/testing"
    16  	"github.com/juju/juju/core/permission"
    17  	"github.com/juju/juju/testcharms"
    18  	jujuversion "github.com/juju/juju/version"
    19  )
    20  
    21  var _ = gc.Suite(&clientMacaroonSuite{})
    22  
    23  // clientMacaroonSuite tests that Client endpoints that are
    24  // independent of the RPC-based API work with
    25  // macaroon authentication.
    26  type clientMacaroonSuite struct {
    27  	apitesting.MacaroonSuite
    28  }
    29  
    30  func (s *clientMacaroonSuite) createTestClient(c *gc.C) *charms.LocalCharmClient {
    31  	username := "testuser@somewhere"
    32  	s.AddModelUser(c, username)
    33  	s.AddControllerUser(c, username, permission.LoginAccess)
    34  	cookieJar := apitesting.NewClearableCookieJar()
    35  	s.DischargerLogin = func() string { return username }
    36  	api := s.OpenAPI(c, nil, cookieJar)
    37  	charmClient, err := charms.NewLocalCharmClient(api)
    38  	c.Assert(err, jc.ErrorIsNil)
    39  
    40  	// Even though we've logged into the API, we want
    41  	// the tests below to exercise the discharging logic
    42  	// so we clear the cookies.
    43  	cookieJar.Clear()
    44  	return charmClient
    45  }
    46  
    47  func (s *clientMacaroonSuite) TestAddLocalCharmWithFailedDischarge(c *gc.C) {
    48  	charmClient := s.createTestClient(c)
    49  	s.DischargerLogin = func() string { return "" }
    50  	charmArchive := testcharms.Repo.CharmArchive(c.MkDir(), "dummy")
    51  	curl := charm.MustParseURL(
    52  		fmt.Sprintf("local:quantal/%s-%d", charmArchive.Meta().Name, charmArchive.Revision()),
    53  	)
    54  	savedURL, err := charmClient.AddLocalCharm(curl, charmArchive, false, jujuversion.Current)
    55  	c.Assert(err, gc.ErrorMatches, `Put https://.+: cannot get discharge from "https://.*": third party refused discharge: cannot discharge: login denied by discharger`)
    56  	c.Assert(savedURL, gc.IsNil)
    57  }
    58  
    59  func (s *clientMacaroonSuite) TestAddLocalCharmSuccess(c *gc.C) {
    60  	charmClient, err := charms.NewLocalCharmClient(s.APIState)
    61  	c.Assert(err, jc.ErrorIsNil)
    62  	charmArchive := testcharms.Repo.CharmArchive(c.MkDir(), "dummy")
    63  	curl := charm.MustParseURL(
    64  		fmt.Sprintf("local:quantal/%s-%d", charmArchive.Meta().Name, charmArchive.Revision()),
    65  	)
    66  	testcharms.CheckCharmReady(c, charmArchive)
    67  
    68  	// Upload an archive with its original revision.
    69  	savedURL, err := charmClient.AddLocalCharm(curl, charmArchive, false, jujuversion.Current)
    70  	// We know that in testing we occasionally see "zip: not a valid zip file" occur.
    71  	// Even after many efforts, we haven't been able to find the source. It almost never
    72  	// happens locally, and we don't see this in production.
    73  	// TODO: remove the skip when we are using the fake charmstore.
    74  	if err != nil {
    75  		if strings.Contains(err.Error(), "zip: not a valid zip file") {
    76  			c.Skip("intermittent charmstore upload issue")
    77  		}
    78  	}
    79  	c.Assert(err, jc.ErrorIsNil)
    80  	c.Assert(savedURL.String(), gc.Equals, curl.String())
    81  }