func (*APIOpenerSuite) TestTimoutClosesAPIOnTimeout(c *gc.C) { var controllerName, accountName, modelName string finished := make(chan struct{}) mockConn := &mockConnection{closed: make(chan struct{})} open := func(_ jujuclient.ClientStore, controllerNameArg, accountNameArg, modelNameArg string) (api.Connection, error) { <-finished controllerName = controllerNameArg accountName = accountNameArg modelName = modelNameArg return mockConn, nil } // have the mock clock only wait a microsecond clock := &mockClock{wait: time.Microsecond} // but tell it to wait five seconds opener := modelcmd.NewTimeoutOpener(modelcmd.OpenFunc(open), clock, 5*time.Second) conn, err := opener.Open(nil, "a-name", "b-name", "c-name") c.Assert(errors.Cause(err), gc.Equals, modelcmd.ErrConnTimedOut) c.Assert(conn, gc.IsNil) // check it was told to wait for 5 seconds c.Assert(clock.duration, gc.Equals, 5*time.Second) // tell the open func to continue now we have timed out close(finished) // wait until the connection has been closed select { case <-mockConn.closed: // continue case <-time.After(5 * time.Second): c.Error("API connection was not closed.") } c.Assert(controllerName, gc.Equals, "a-name") c.Assert(accountName, gc.Equals, "b-name") c.Assert(modelName, gc.Equals, "c-name") }
func (s *KillSuite) TestKillAPIPermErrFails(c *gc.C) { testDialer := func(_ jujuclient.ClientStore, controllerName, accountName, modelName string) (api.Connection, error) { return nil, common.ErrPerm } cmd := controller.NewKillCommandForTest(nil, nil, s.store, nil, clock.WallClock, modelcmd.OpenFunc(testDialer)) _, err := testing.RunCommand(c, cmd, "local.test1", "-y") c.Assert(err, gc.ErrorMatches, "cannot destroy controller: permission denied") checkControllerExistsInStore(c, "local.test1", s.store) }
// wrapKillCommand provides the common wrapping used by tests and // the default NewKillCommand above. func wrapKillCommand(kill *killCommand, apiOpen modelcmd.APIOpener, clock clock.Clock) cmd.Command { if apiOpen == nil { apiOpen = modelcmd.OpenFunc(kill.JujuCommandBase.NewAPIRoot) } openStrategy := modelcmd.NewTimeoutOpener(apiOpen, clock, 10*time.Second) return modelcmd.WrapController( kill, modelcmd.WrapControllerSkipControllerFlags, modelcmd.WrapControllerSkipDefaultController, modelcmd.WrapControllerAPIOpener(openStrategy), ) }
func (*APIOpenerSuite) TestTimoutErrors(c *gc.C) { var controllerName, modelName string open := func(_ jujuclient.ClientStore, controllerNameArg, modelNameArg string) (api.Connection, error) { controllerName = controllerNameArg modelName = modelNameArg return nil, errors.New("boom") } opener := modelcmd.NewTimeoutOpener(modelcmd.OpenFunc(open), clock.WallClock, 10*time.Second) conn, err := opener.Open(nil, "a-name", "b-name") c.Assert(err, gc.ErrorMatches, "boom") c.Assert(conn, gc.IsNil) c.Assert(controllerName, gc.Equals, "a-name") c.Assert(modelName, gc.Equals, "b-name") }
func (*APIOpenerSuite) TestTimoutSuccess(c *gc.C) { var controllerName, accountName, modelName string open := func(_ jujuclient.ClientStore, controllerNameArg, accountNameArg, modelNameArg string) (api.Connection, error) { controllerName = controllerNameArg accountName = accountNameArg modelName = modelNameArg return &mockConnection{}, nil } opener := modelcmd.NewTimeoutOpener(modelcmd.OpenFunc(open), clock.WallClock, 10*time.Second) conn, err := opener.Open(nil, "a-name", "b-name", "c-name") c.Assert(err, jc.ErrorIsNil) c.Assert(conn, gc.NotNil) c.Assert(controllerName, gc.Equals, "a-name") c.Assert(accountName, gc.Equals, "b-name") c.Assert(modelName, gc.Equals, "c-name") }
func (*APIOpenerSuite) TestPassthrough(c *gc.C) { var controllerName, modelName string open := func(_ jujuclient.ClientStore, controllerNameArg, modelNameArg string) (api.Connection, error) { controllerName = controllerNameArg modelName = modelNameArg // Lets do the bad thing and return both a connection instance // and an error to check they both come through. return &mockConnection{}, errors.New("boom") } opener := modelcmd.OpenFunc(open) conn, err := opener.Open(nil, "a-name", "b-name") c.Assert(err, gc.ErrorMatches, "boom") c.Assert(conn, gc.NotNil) c.Assert(controllerName, gc.Equals, "a-name") c.Assert(modelName, gc.Equals, "b-name") }
func (s *KillSuite) TestKillEarlyAPIConnectionTimeout(c *gc.C) { clock := &mockClock{} stop := make(chan struct{}) defer close(stop) testDialer := func(_ jujuclient.ClientStore, controllerName, accountName, modelName string) (api.Connection, error) { <-stop return nil, errors.New("kill command waited too long") } cmd := controller.NewKillCommandForTest(nil, nil, s.store, nil, clock, modelcmd.OpenFunc(testDialer)) ctx, err := testing.RunCommand(c, cmd, "local.test1", "-y") c.Check(err, jc.ErrorIsNil) c.Check(testing.Stderr(ctx), jc.Contains, "Unable to open API: open connection timed out") checkControllerRemovedFromStore(c, "local.test1", s.store) // Check that we were actually told to wait for 10s. c.Assert(clock.wait, gc.Equals, 10*time.Second) }
func (s *UpgradeCharmSuite) SetUpTest(c *gc.C) { s.IsolationSuite.SetUpTest(c) s.Stub.ResetCalls() // Create persistent cookies in a temporary location. cookieFile := filepath.Join(c.MkDir(), "cookies") s.PatchEnvironment("JUJU_COOKIEFILE", cookieFile) s.deployResources = func( applicationID string, chID jujucharmstore.CharmID, csMac *macaroon.Macaroon, filesAndRevisions map[string]string, resources map[string]charmresource.Meta, conn base.APICallCloser, ) (ids map[string]string, err error) { s.AddCall("DeployResources", applicationID, chID, csMac, filesAndRevisions, resources, conn) return nil, s.NextErr() } s.resolveCharm = func( resolveWithChannel func(*charm.URL) (*charm.URL, csclientparams.Channel, []string, error), conf *config.Config, url *charm.URL, ) (*charm.URL, csclientparams.Channel, []string, error) { s.AddCall("ResolveCharm", resolveWithChannel, conf, url) if err := s.NextErr(); err != nil { return nil, csclientparams.NoChannel, nil, err } return s.resolvedCharmURL, csclientparams.StableChannel, []string{"quantal"}, nil } currentCharmURL := charm.MustParseURL("cs:quantal/foo-1") latestCharmURL := charm.MustParseURL("cs:quantal/foo-2") s.resolvedCharmURL = latestCharmURL s.apiConnection = mockAPIConnection{ bestFacadeVersion: 2, serverVersion: &version.Number{ Major: 1, Minor: 2, Patch: 3, }, } s.charmAdder = mockCharmAdder{} s.charmClient = mockCharmClient{ charmInfo: &charms.CharmInfo{ Meta: &charm.Meta{}, }, } s.charmUpgradeClient = mockCharmUpgradeClient{charmURL: currentCharmURL} s.modelConfigGetter = mockModelConfigGetter{} s.resourceLister = mockResourceLister{} store := jujuclienttesting.NewMemStore() store.CurrentControllerName = "foo" store.Controllers["foo"] = jujuclient.ControllerDetails{} store.Models["foo"] = &jujuclient.ControllerModels{ CurrentModel: "admin@local/bar", Models: map[string]jujuclient.ModelDetails{"admin@local/bar": {}}, } apiOpener := modelcmd.OpenFunc(func(store jujuclient.ClientStore, controller, model string) (api.Connection, error) { s.AddCall("OpenAPI", store, controller, model) return &s.apiConnection, nil }) s.cmd = NewUpgradeCharmCommandForTest( store, apiOpener, s.deployResources, s.resolveCharm, func(conn api.Connection, bakeryClient *httpbakery.Client, channel csclientparams.Channel) CharmAdder { s.AddCall("NewCharmAdder", conn, bakeryClient, channel) s.PopNoErr() return &s.charmAdder }, func(conn api.Connection) CharmClient { s.AddCall("NewCharmClient", conn) s.PopNoErr() return &s.charmClient }, func(conn api.Connection) CharmUpgradeClient { s.AddCall("NewCharmUpgradeClient", conn) s.PopNoErr() return &s.charmUpgradeClient }, func(conn api.Connection) ModelConfigGetter { s.AddCall("NewModelConfigGetter", conn) return &s.modelConfigGetter }, func(conn api.Connection) (ResourceLister, error) { s.AddCall("NewResourceLister", conn) return &s.resourceLister, s.NextErr() }, ) }