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