github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/romulus/setplan/set_plan_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package setplan_test
     5  
     6  import (
     7  	"encoding/json"
     8  	"fmt"
     9  	"net/url"
    10  	stdtesting "testing"
    11  
    12  	"github.com/juju/cmd/cmdtesting"
    13  	"github.com/juju/errors"
    14  	"github.com/juju/testing"
    15  	jc "github.com/juju/testing/checkers"
    16  	gc "gopkg.in/check.v1"
    17  	"gopkg.in/juju/charm.v6"
    18  	"gopkg.in/macaroon-bakery.v2-unstable/bakery"
    19  	"gopkg.in/macaroon-bakery.v2-unstable/bakery/checkers"
    20  	"gopkg.in/macaroon.v2-unstable"
    21  
    22  	rcmd "github.com/juju/juju/cmd/juju/romulus"
    23  	"github.com/juju/juju/cmd/juju/romulus/setplan"
    24  	"github.com/juju/juju/cmd/modelcmd"
    25  	jjjtesting "github.com/juju/juju/juju/testing"
    26  	"github.com/juju/juju/state"
    27  	"github.com/juju/juju/testcharms"
    28  	jjtesting "github.com/juju/juju/testing"
    29  )
    30  
    31  func TestPackage(t *stdtesting.T) {
    32  	jjtesting.MgoTestPackage(t)
    33  }
    34  
    35  var _ = gc.Suite(&setPlanCommandSuite{})
    36  
    37  type setPlanCommandSuite struct {
    38  	jjjtesting.JujuConnSuite
    39  
    40  	mockAPI  *mockapi
    41  	charmURL string
    42  }
    43  
    44  func (s *setPlanCommandSuite) SetUpTest(c *gc.C) {
    45  	s.JujuConnSuite.SetUpTest(c)
    46  
    47  	ch := testcharms.Repo.CharmDir("dummy")
    48  	curl := charm.MustParseURL(
    49  		fmt.Sprintf("local:quantal/%s-%d", ch.Meta().Name, ch.Revision()),
    50  	)
    51  	s.charmURL = curl.String()
    52  	charmInfo := state.CharmInfo{
    53  		Charm:       ch,
    54  		ID:          curl,
    55  		StoragePath: "dummy-path",
    56  		SHA256:      "dummy-1",
    57  	}
    58  	dummyCharm, err := s.State.AddCharm(charmInfo)
    59  	c.Assert(err, jc.ErrorIsNil)
    60  	s.AddTestingApplication(c, "mysql", dummyCharm)
    61  
    62  	mockAPI, err := newMockAPI()
    63  	c.Assert(err, jc.ErrorIsNil)
    64  	s.mockAPI = mockAPI
    65  
    66  	s.PatchValue(setplan.NewAuthorizationClient, setplan.APIClientFnc(s.mockAPI))
    67  	s.PatchValue(&rcmd.GetMeteringURLForModelCmd, func(c *modelcmd.ModelCommandBase) (string, error) {
    68  		return "http://example.com", nil
    69  	})
    70  }
    71  
    72  func (s setPlanCommandSuite) TestSetPlanCommand(c *gc.C) {
    73  	tests := []struct {
    74  		about       string
    75  		plan        string
    76  		application string
    77  		err         string
    78  		apiErr      error
    79  		apiCalls    []testing.StubCall
    80  	}{{
    81  		about:       "all is well",
    82  		plan:        "bob/default",
    83  		application: "mysql",
    84  		apiCalls: []testing.StubCall{{
    85  			FuncName: "Authorize",
    86  			Args: []interface{}{
    87  				s.State.ModelUUID(),
    88  				s.charmURL,
    89  				"mysql",
    90  			},
    91  		}},
    92  	}, {
    93  		about:       "invalid application name",
    94  		plan:        "bob/default",
    95  		application: "mysql-0",
    96  		err:         "invalid application name \"mysql-0\"",
    97  	}, {
    98  		about:       "unknown application",
    99  		plan:        "bob/default",
   100  		application: "wordpress",
   101  		err:         "application \"wordpress\" not found.*",
   102  	}, {
   103  		about:       "unknown application",
   104  		plan:        "bob/default",
   105  		application: "mysql",
   106  		apiErr:      errors.New("some strange error"),
   107  		err:         "some strange error",
   108  	},
   109  	}
   110  	for i, test := range tests {
   111  		c.Logf("running test %d: %v", i, test.about)
   112  		s.mockAPI.ResetCalls()
   113  		if test.apiErr != nil {
   114  			s.mockAPI.SetErrors(test.apiErr)
   115  		}
   116  		_, err := cmdtesting.RunCommand(c, setplan.NewSetPlanCommand(), test.application, test.plan)
   117  		if test.err == "" {
   118  			c.Assert(err, jc.ErrorIsNil)
   119  			c.Assert(s.mockAPI.Calls(), gc.HasLen, 1)
   120  			s.mockAPI.CheckCalls(c, test.apiCalls)
   121  
   122  			app, err := s.State.Application("mysql")
   123  			c.Assert(err, jc.ErrorIsNil)
   124  			svcMacaroon := app.MetricCredentials()
   125  			data, err := json.Marshal(macaroon.Slice{s.mockAPI.macaroon})
   126  			c.Assert(err, jc.ErrorIsNil)
   127  			c.Assert(svcMacaroon, gc.DeepEquals, data)
   128  		} else {
   129  			c.Assert(err, gc.ErrorMatches, test.err)
   130  			c.Assert(s.mockAPI.Calls(), gc.HasLen, 0)
   131  		}
   132  	}
   133  }
   134  
   135  func (s *setPlanCommandSuite) TestNoArgs(c *gc.C) {
   136  	_, err := cmdtesting.RunCommand(c, setplan.NewSetPlanCommand())
   137  	c.Assert(err, gc.ErrorMatches, "need to specify application name and plan url")
   138  }
   139  
   140  func newMockAPI() (*mockapi, error) {
   141  	kp, err := bakery.GenerateKey()
   142  	if err != nil {
   143  		return nil, errors.Trace(err)
   144  	}
   145  	svc, err := bakery.NewService(bakery.NewServiceParams{
   146  		Location: "omnibus",
   147  		Key:      kp,
   148  	})
   149  	if err != nil {
   150  		return nil, errors.Trace(err)
   151  	}
   152  	return &mockapi{
   153  		service: svc,
   154  	}, nil
   155  }
   156  
   157  type mockapi struct {
   158  	testing.Stub
   159  
   160  	service  *bakery.Service
   161  	macaroon *macaroon.Macaroon
   162  }
   163  
   164  func (m *mockapi) Authorize(modelUUID, charmURL, applicationName, plan string, visitWebPage func(*url.URL) error) (*macaroon.Macaroon, error) {
   165  	err := m.NextErr()
   166  	if err != nil {
   167  		return nil, errors.Trace(err)
   168  	}
   169  	m.AddCall("Authorize", modelUUID, charmURL, applicationName)
   170  	macaroon, err := m.service.NewMacaroon(
   171  
   172  		[]checkers.Caveat{
   173  			checkers.DeclaredCaveat("environment", modelUUID),
   174  			checkers.DeclaredCaveat("charm", charmURL),
   175  			checkers.DeclaredCaveat("service", applicationName),
   176  			checkers.DeclaredCaveat("plan", plan),
   177  		})
   178  
   179  	if err != nil {
   180  		return nil, errors.Trace(err)
   181  	}
   182  	m.macaroon = macaroon
   183  	return m.macaroon, nil
   184  }