Separate model and controller config at backend #5590

Merged
merged 5 commits into from Jun 11, 2016
@@ -19,6 +19,7 @@ import (
"github.com/juju/juju/agent/agentbootstrap"
"github.com/juju/juju/apiserver/params"
"github.com/juju/juju/constraints"
+ "github.com/juju/juju/controller"
"github.com/juju/juju/environs"
"github.com/juju/juju/environs/config"
"github.com/juju/juju/instance"
@@ -168,14 +169,28 @@ LXC_BRIDGE="ignored"`[1:])
c.Assert(err, jc.ErrorIsNil)
c.Assert(user.PasswordValid(testing.DefaultMongoPassword), jc.IsTrue)
+ // Check controller config
+ controllerCfg, err := st.ControllerConfig()
+ c.Assert(err, jc.ErrorIsNil)
+ c.Assert(controllerCfg, jc.DeepEquals, controller.Config{
+ "controller-uuid": testing.ModelTag.Id(),
+ "ca-cert": testing.CACert,
+ "ca-private-key": testing.CAKey,
+ "state-port": 1234,
+ // Dummy provider uses a random port, which is added to cfg used to create environment.
+ "api-port": controller.Config(modelCfg.AllAttrs()).APIPort(),
+ })
+
// Check that controller model configuration has been added, and
// model constraints set.
newModelCfg, err := st.ModelConfig()
c.Assert(err, jc.ErrorIsNil)
// Add in the cloud attributes.
expectedAttrs := modelCfg.AllAttrs()
expectedAttrs["apt-mirror"] = "http://mirror"
- c.Assert(newModelCfg.AllAttrs(), gc.DeepEquals, expectedAttrs)
+ controller.RemoveControllerAttributes(expectedAttrs)
+ c.Assert(newModelCfg.AllAttrs(), jc.DeepEquals, expectedAttrs)
+
gotModelConstraints, err := st.ModelConstraints()
c.Assert(err, jc.ErrorIsNil)
c.Assert(gotModelConstraints, gc.DeepEquals, expectModelConstraints)
@@ -7,6 +7,7 @@ import (
"github.com/juju/juju/api/base"
apiwatcher "github.com/juju/juju/api/watcher"
"github.com/juju/juju/apiserver/params"
+ "github.com/juju/juju/controller"
"github.com/juju/juju/environs/config"
"github.com/juju/juju/watcher"
)
@@ -47,3 +48,13 @@ func (e *ModelWatcher) ModelConfig() (*config.Config, error) {
}
return conf, nil
}
+
+// ControllerConfig returns the current controller configuration.
+func (e *ModelWatcher) ControllerConfig() (controller.Config, error) {
+ var result params.ControllerConfigResult
+ err := e.facade.FacadeCall("ControllerConfig", nil, &result)
+ if err != nil {
+ return nil, err
+ }
+ return controller.Config(result.Config), nil
+}
View
@@ -27,6 +27,7 @@ import (
"github.com/juju/juju/api/upgrader"
"github.com/juju/juju/network"
"github.com/juju/juju/rpc"
+ "github.com/juju/utils/set"
)
// Info encapsulates information about a server holding juju state and
@@ -71,11 +72,28 @@ type Info struct {
Nonce string `yaml:",omitempty"`
}
+// Ports returns the unique ports for the api addresses.
+func (info *Info) Ports() []int {
+ ports := set.NewInts()
+ hostPorts, err := network.ParseHostPorts(info.Addrs...)
+ if err != nil {
+ // Addresses have already been validated.
+ panic(err)
+ }
+ for _, hp := range hostPorts {
+ ports.Add(hp.Port)
+ }
+ return ports.Values()
+}
+
// Validate validates the API info.
func (info *Info) Validate() error {
if len(info.Addrs) == 0 {
return errors.NotValidf("missing addresses")
}
+ if _, err := network.ParseHostPorts(info.Addrs...); err != nil {
+ return errors.NotValidf("host addresses")
+ }
if info.CACert == "" {
return errors.NotValidf("missing CA certificate")
}
@@ -34,20 +34,10 @@ func (s *modelmanagerSuite) TestConfigSkeleton(c *gc.C) {
modelManager := s.OpenAPI(c)
result, err := modelManager.ConfigSkeleton("", "")
c.Assert(err, jc.ErrorIsNil)
-
- // The apiPort changes every test run as the dummy provider
- // looks for a random open port.
- apiPort := s.Environ.Config().APIPort()
-
- // Numbers coming over the api are floats, not ints.
c.Assert(result, jc.DeepEquals, params.ModelConfig{
"type": "dummy",
"controller-uuid": coretesting.ModelTag.Id(),
- "ca-cert": coretesting.CACert,
- "state-port": float64(1234),
- "api-port": float64(apiPort),
})
-
}
func (s *modelmanagerSuite) TestCreateModelBadUser(c *gc.C) {
@@ -16,7 +16,7 @@ import (
"gopkg.in/macaroon-bakery.v1/httpbakery"
"github.com/juju/juju/api"
- "github.com/juju/juju/environs/config"
+ "github.com/juju/juju/controller"
jujutesting "github.com/juju/juju/juju/testing"
"github.com/juju/juju/testing/factory"
)
@@ -53,7 +53,7 @@ func (s *MacaroonSuite) SetUpTest(c *gc.C) {
return []checkers.Caveat{checkers.DeclaredCaveat("username", username)}, nil
})
s.JujuConnSuite.ConfigAttrs = map[string]interface{}{
- config.IdentityURL: s.discharger.Location(),
+ controller.IdentityURL: s.discharger.Location(),
}
s.JujuConnSuite.SetUpTest(c)
}
@@ -51,11 +51,7 @@ func NewAddresserAPI(
// getNetworkingEnviron checks if the environment implements NetworkingEnviron
// and also if it supports IP address allocation.
func (api *AddresserAPI) getNetworkingEnviron() (environs.NetworkingEnviron, bool, error) {
- config, err := api.st.ModelConfig()
- if err != nil {
- return nil, false, errors.Annotate(err, "getting model config")
- }
- env, err := environs.New(config)
+ env, err := environs.GetEnviron(api.st, environs.New)
if err != nil {
return nil, false, errors.Annotate(err, "validating model config")
}
@@ -91,7 +91,7 @@ func (s *AddresserSuite) TestCanDeallocateAddressesConfigGetFailure(c *gc.C) {
s.st.stub.SetErrors(errors.New("ouch"))
result := s.api.CanDeallocateAddresses()
- c.Assert(result.Error, gc.ErrorMatches, "getting model config: ouch")
+ c.Assert(result.Error, gc.ErrorMatches, "validating model config: ouch")
c.Assert(result.Result, jc.IsFalse)
}
@@ -194,7 +194,7 @@ func (s *AddresserSuite) TestCleanupIPAddressesConfigGetFailure(c *gc.C) {
// First action is getting the environment configuration,
// so the injected error is returned here.
apiErr := s.api.CleanupIPAddresses()
- c.Assert(apiErr.Error, gc.ErrorMatches, "getting model config: ouch")
+ c.Assert(apiErr.Error, gc.ErrorMatches, "validating model config: ouch")
// Still has two dead addresses.
dead, err = s.st.DeadIPAddresses()
@@ -14,6 +14,7 @@ import (
"gopkg.in/juju/names.v2"
"github.com/juju/juju/apiserver/addresser"
+ "github.com/juju/juju/controller"
"github.com/juju/juju/environs"
"github.com/juju/juju/environs/config"
"github.com/juju/juju/instance"
@@ -92,6 +93,16 @@ func (mst *mockState) ModelConfig() (*config.Config, error) {
return mst.config, nil
}
+// ControllerConfig implements StateInterface.
+func (*mockState) ControllerConfig() (controller.Config, error) {
+ return map[string]interface{}{
+ controller.ControllerUUIDKey: coretesting.ModelTag.Id(),
+ controller.CACertKey: coretesting.CACert,
+ controller.CAPrivateKey: coretesting.CAKey,
+ controller.ApiPort: 4321,
+ }, nil
+}
+
// setConfig updates the environ config stored internally. Triggers a
// change event for all created config watchers.
func (mst *mockState) setConfig(c *gc.C, newConfig *config.Config) {
@@ -4,7 +4,7 @@
package addresser
import (
- "github.com/juju/juju/environs/config"
+ "github.com/juju/juju/environs"
"github.com/juju/juju/instance"
"github.com/juju/juju/network"
"github.com/juju/juju/state"
@@ -28,8 +28,7 @@ type StateIPAddress interface {
// StateInterface defines the needed methods of state.State
// for the work of the Addresser API.
type StateInterface interface {
- // ModelConfig retrieves the model configuration.
- ModelConfig() (*config.Config, error)
+ environs.EnvironConfigGetter
// DeadIPAddresses retrieves all dead IP addresses.
DeadIPAddresses() ([]StateIPAddress, error)
@@ -26,9 +26,14 @@ var (
findTools = tools.FindTools
)
+type stateInterface interface {
+ ModelGetter
+ environs.EnvironConfigGetter
+}
+
// AgentToolsAPI implements the API used by the machine model worker.
type AgentToolsAPI struct {
- st EnvironGetter
+ st stateInterface
authorizer common.Authorizer
// tools lookup
findTools toolsFinder
@@ -45,8 +50,8 @@ func NewAgentToolsAPI(st *state.State, resources *common.Resources, authorizer c
}, nil
}
-// EnvironGetter represents a struct that can provide a state.Environment.
-type EnvironGetter interface {
+// ModelGetter represents a struct that can provide a state.Model.
+type ModelGetter interface {
Model() (*state.Model, error)
}
@@ -55,13 +60,13 @@ type envVersionUpdater func(*state.Model, version.Number) error
var newEnvirons = environs.New
-func checkToolsAvailability(cfg *config.Config, finder toolsFinder) (version.Number, error) {
- currentVersion, ok := cfg.AgentVersion()
+func checkToolsAvailability(getter environs.EnvironConfigGetter, modelCfg *config.Config, finder toolsFinder) (version.Number, error) {
+ currentVersion, ok := modelCfg.AgentVersion()
if !ok || currentVersion == version.Zero {
return version.Zero, nil
}
- env, err := newEnvirons(cfg)
+ env, err := environs.GetEnviron(getter, newEnvirons)
if err != nil {
return version.Zero, errors.Annotatef(err, "cannot make model")
}
@@ -71,7 +76,7 @@ func checkToolsAvailability(cfg *config.Config, finder toolsFinder) (version.Num
// We'll try the released stream first, then fall back to the current configured stream
// if no released tools are found.
vers, err := finder(env, currentVersion.Major, currentVersion.Minor, tools.ReleasedStream, coretools.Filter{})
- preferredStream := tools.PreferredStream(&currentVersion, cfg.Development(), cfg.AgentStream())
+ preferredStream := tools.PreferredStream(&currentVersion, modelCfg.Development(), modelCfg.AgentStream())
if preferredStream != tools.ReleasedStream && errors.Cause(err) == coretools.ErrNoMatches {
vers, err = finder(env, currentVersion.Major, currentVersion.Minor, preferredStream, coretools.Filter{})
}
@@ -84,7 +89,7 @@ func checkToolsAvailability(cfg *config.Config, finder toolsFinder) (version.Num
return newest, nil
}
-var envConfig = func(e *state.Model) (*config.Config, error) {
+var modelConfig = func(e *state.Model) (*config.Config, error) {
return e.Config()
}
@@ -93,16 +98,16 @@ func envVersionUpdate(env *state.Model, ver version.Number) error {
return env.UpdateLatestToolsVersion(ver)
}
-func updateToolsAvailability(st EnvironGetter, finder toolsFinder, update envVersionUpdater) error {
- env, err := st.Model()
+func updateToolsAvailability(st stateInterface, finder toolsFinder, update envVersionUpdater) error {
+ model, err := st.Model()
if err != nil {
return errors.Annotate(err, "cannot get model")
}
- cfg, err := envConfig(env)
+ cfg, err := modelConfig(model)
if err != nil {
return errors.Annotate(err, "cannot get config")
}
- ver, err := checkToolsAvailability(cfg, finder)
+ ver, err := checkToolsAvailability(st, cfg, finder)
if err != nil {
if errors.IsNotFound(err) {
// No newer tools, so exit silently.
@@ -114,7 +119,7 @@ func updateToolsAvailability(st EnvironGetter, finder toolsFinder, update envVer
logger.Debugf("tools lookup returned version Zero, this should only happen during bootstrap.")
return nil
}
- return update(env, ver)
+ return update(model, ver)
}
// UpdateToolsAvailable invokes a lookup and further update in environ
Oops, something went wrong.