github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/application/consume_test.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package application_test 5 6 import ( 7 "github.com/juju/cmd" 8 "github.com/juju/cmd/cmdtesting" 9 "github.com/juju/errors" 10 "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 14 apitesting "github.com/juju/juju/api/testing" 15 "github.com/juju/juju/apiserver/params" 16 "github.com/juju/juju/cmd/juju/application" 17 "github.com/juju/juju/core/crossmodel" 18 "github.com/juju/juju/core/model" 19 "github.com/juju/juju/jujuclient" 20 coretesting "github.com/juju/juju/testing" 21 ) 22 23 type ConsumeSuite struct { 24 testing.IsolationSuite 25 mockAPI *mockConsumeAPI 26 store *jujuclient.MemStore 27 } 28 29 var _ = gc.Suite(&ConsumeSuite{}) 30 31 func (s *ConsumeSuite) SetUpTest(c *gc.C) { 32 s.IsolationSuite.SetUpTest(c) 33 s.mockAPI = &mockConsumeAPI{Stub: &testing.Stub{}} 34 35 // Set up the current controller, and write just enough info 36 // so we don't try to refresh 37 controllerName := "test-master" 38 s.store = jujuclient.NewMemStore() 39 s.store.CurrentControllerName = controllerName 40 s.store.Controllers[controllerName] = jujuclient.ControllerDetails{} 41 s.store.Models[controllerName] = &jujuclient.ControllerModels{ 42 CurrentModel: "bob/test", 43 Models: map[string]jujuclient.ModelDetails{ 44 "bob/test": {ModelUUID: "test-uuid", ModelType: model.IAAS}, 45 "bob/prod": {ModelUUID: "prod-uuid", ModelType: model.IAAS}, 46 }, 47 } 48 s.store.Accounts[controllerName] = jujuclient.AccountDetails{ 49 User: "bob", 50 } 51 } 52 53 func (s *ConsumeSuite) runConsume(c *gc.C, args ...string) (*cmd.Context, error) { 54 return cmdtesting.RunCommand(c, application.NewConsumeCommandForTest(s.store, s.mockAPI, s.mockAPI), args...) 55 } 56 57 func (s *ConsumeSuite) TestNoArguments(c *gc.C) { 58 _, err := s.runConsume(c) 59 c.Assert(err, gc.ErrorMatches, "no remote offer specified") 60 } 61 62 func (s *ConsumeSuite) TestTooManyArguments(c *gc.C) { 63 _, err := s.runConsume(c, "model.application", "alias", "something else") 64 c.Assert(err, gc.ErrorMatches, `unrecognized args: \["something else"\]`, gc.Commentf("details: %s", errors.Details(err))) 65 } 66 67 func (s *ConsumeSuite) TestInvalidRemoteApplication(c *gc.C) { 68 badApplications := []string{ 69 "application", 70 "user/model.application:endpoint", 71 "user/model", 72 "unknown:/wherever", 73 } 74 for _, bad := range badApplications { 75 c.Logf(bad) 76 _, err := s.runConsume(c, bad) 77 c.Check(err != nil, jc.IsTrue) 78 } 79 } 80 81 func (s *ConsumeSuite) TestErrorFromAPI(c *gc.C) { 82 s.mockAPI.SetErrors(errors.New("infirmary")) 83 _, err := s.runConsume(c, "model.application") 84 c.Assert(err, gc.ErrorMatches, "infirmary") 85 } 86 87 func (s *ConsumeSuite) assertSuccessModelDotApplication(c *gc.C, alias string) { 88 s.mockAPI.localName = "mary-weep" 89 var ( 90 ctx *cmd.Context 91 err error 92 ) 93 if alias != "" { 94 ctx, err = s.runConsume(c, "ctrl:booster.uke", alias) 95 } else { 96 ctx, err = s.runConsume(c, "ctrl:booster.uke") 97 } 98 c.Assert(err, jc.ErrorIsNil) 99 mac, err := apitesting.NewMacaroon("id") 100 c.Assert(err, jc.ErrorIsNil) 101 s.mockAPI.CheckCalls(c, []testing.StubCall{ 102 {"GetConsumeDetails", []interface{}{"bob/booster.uke"}}, 103 {"Consume", []interface{}{crossmodel.ConsumeApplicationArgs{ 104 Offer: params.ApplicationOfferDetails{OfferName: "an offer", OfferURL: "ctrl:bob/booster.uke"}, 105 ApplicationAlias: alias, 106 Macaroon: mac, 107 ControllerInfo: &crossmodel.ControllerInfo{ 108 ControllerTag: coretesting.ControllerTag, 109 Alias: "controller-alias", 110 Addrs: []string{"192.168.1:1234"}, 111 CACert: coretesting.CACert, 112 }, 113 }, 114 }}, 115 {"Close", nil}, 116 {"Close", nil}, 117 }) 118 c.Assert(cmdtesting.Stderr(ctx), gc.Equals, "Added ctrl:bob/booster.uke as mary-weep\n") 119 } 120 121 func (s *ConsumeSuite) TestSuccessModelDotApplication(c *gc.C) { 122 s.assertSuccessModelDotApplication(c, "") 123 } 124 125 func (s *ConsumeSuite) TestSuccessModelDotApplicationWithAlias(c *gc.C) { 126 s.assertSuccessModelDotApplication(c, "alias") 127 } 128 129 type mockConsumeAPI struct { 130 *testing.Stub 131 132 localName string 133 } 134 135 func (a *mockConsumeAPI) Close() error { 136 a.MethodCall(a, "Close") 137 return a.NextErr() 138 } 139 140 func (a *mockConsumeAPI) Consume(arg crossmodel.ConsumeApplicationArgs) (string, error) { 141 a.MethodCall(a, "Consume", arg) 142 return a.localName, a.NextErr() 143 } 144 145 func (a *mockConsumeAPI) GetConsumeDetails(url string) (params.ConsumeOfferDetails, error) { 146 a.MethodCall(a, "GetConsumeDetails", url) 147 mac, err := apitesting.NewMacaroon("id") 148 if err != nil { 149 return params.ConsumeOfferDetails{}, err 150 } 151 return params.ConsumeOfferDetails{ 152 Offer: ¶ms.ApplicationOfferDetails{OfferName: "an offer", OfferURL: "bob/booster.uke"}, 153 Macaroon: mac, 154 ControllerInfo: ¶ms.ExternalControllerInfo{ 155 ControllerTag: coretesting.ControllerTag.String(), 156 Alias: "controller-alias", 157 Addrs: []string{"192.168.1:1234"}, 158 CACert: coretesting.CACert, 159 }, 160 }, a.NextErr() 161 }