Example #1
0
func (s *InitializeSuite) TestDoubleInitializeConfig(c *gc.C) {
	cfg := testing.EnvironConfig(c)
	owner := names.NewLocalUserTag("initialize-admin")

	mgoInfo := statetesting.NewMongoInfo()
	dialOpts := statetesting.NewDialOpts()

	st, err := state.Initialize(owner, mgoInfo, cfg, dialOpts, state.Policy(nil))
	c.Assert(err, jc.ErrorIsNil)
	st.Close()

	_, err = state.Initialize(owner, mgoInfo, cfg, dialOpts, state.Policy(nil))
	c.Assert(err, gc.ErrorMatches, "already initialized")
}
Example #2
0
func (s *InitializeSuite) testBadModelConfig(c *gc.C, update map[string]interface{}, remove []string, expect string) {
	good := testing.CustomModelConfig(c, testing.Attrs{"uuid": testing.ModelTag.Id()})
	bad, err := good.Apply(update)
	c.Assert(err, jc.ErrorIsNil)
	bad, err = bad.Remove(remove)
	c.Assert(err, jc.ErrorIsNil)

	owner := names.NewLocalUserTag("initialize-admin")
	controllerCfg := testing.FakeControllerConfig()

	args := state.InitializeParams{
		Clock:            clock.WallClock,
		ControllerConfig: controllerCfg,
		ControllerModelArgs: state.ModelArgs{
			CloudName:               "dummy",
			CloudRegion:             "dummy-region",
			Owner:                   owner,
			Config:                  bad,
			StorageProviderRegistry: storage.StaticProviderRegistry{},
		},
		CloudName: "dummy",
		Cloud: cloud.Cloud{
			Type:      "dummy",
			AuthTypes: []cloud.AuthType{cloud.EmptyAuthType},
			Regions:   []cloud.Region{{Name: "dummy-region"}},
		},
		MongoInfo:     statetesting.NewMongoInfo(),
		MongoDialOpts: mongotest.DialOpts(),
	}
	_, err = state.Initialize(args)
	c.Assert(err, gc.ErrorMatches, expect)

	args.ControllerModelArgs.Config = good
	st, err := state.Initialize(args)
	c.Assert(err, jc.ErrorIsNil)
	st.Close()

	s.openState(c, st.ModelTag())
	err = s.State.UpdateModelConfig(update, remove, nil)
	c.Assert(err, gc.ErrorMatches, expect)

	// ModelConfig remains inviolate.
	cfg, err := s.State.ModelConfig()
	c.Assert(err, jc.ErrorIsNil)
	goodWithDefaults, err := config.New(config.UseDefaults, good.AllAttrs())
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(cfg.AllAttrs(), jc.DeepEquals, goodWithDefaults.AllAttrs())
}
Example #3
0
func (s *InitializeSuite) TestInitializeWithInvalidCredentialType(c *gc.C) {
	owner := names.NewLocalUserTag("initialize-admin")
	modelCfg := testing.ModelConfig(c)
	controllerCfg := testing.FakeControllerConfig()
	credentialTag := names.NewCloudCredentialTag("dummy/" + owner.Canonical() + "/borken")
	_, err := state.Initialize(state.InitializeParams{
		Clock:            clock.WallClock,
		ControllerConfig: controllerCfg,
		ControllerModelArgs: state.ModelArgs{
			CloudName:               "dummy",
			Owner:                   owner,
			Config:                  modelCfg,
			StorageProviderRegistry: storage.StaticProviderRegistry{},
		},
		CloudName: "dummy",
		Cloud: cloud.Cloud{
			Type: "dummy",
			AuthTypes: []cloud.AuthType{
				cloud.AccessKeyAuthType, cloud.OAuth1AuthType,
			},
		},
		CloudCredentials: map[names.CloudCredentialTag]cloud.Credential{
			credentialTag: cloud.NewCredential(cloud.UserPassAuthType, nil),
		},
		MongoInfo:     statetesting.NewMongoInfo(),
		MongoDialOpts: mongotest.DialOpts(),
	})
	c.Assert(err, gc.ErrorMatches,
		`validating initialization args: validating cloud credentials: credential "dummy/initialize-admin@local/borken" with auth-type "userpass" is not supported \(expected one of \["access-key" "oauth1"\]\)`,
	)
}
Example #4
0
func (s *InitializeSuite) TestInitialize(c *gc.C) {
	cfg := testing.EnvironConfig(c)
	initial := cfg.AllAttrs()
	st, err := state.Initialize(state.TestingStateInfo(), cfg, state.TestingDialOpts(), state.Policy(nil))
	c.Assert(err, gc.IsNil)
	c.Assert(st, gc.NotNil)
	err = st.Close()
	c.Assert(err, gc.IsNil)

	s.openState(c)

	cfg, err = s.State.EnvironConfig()
	c.Assert(err, gc.IsNil)
	c.Assert(cfg.AllAttrs(), gc.DeepEquals, initial)

	env, err := s.State.Environment()
	c.Assert(err, gc.IsNil)
	entity, err := s.State.FindEntity("environment-" + env.UUID())
	c.Assert(err, gc.IsNil)
	annotator := entity.(state.Annotator)
	annotations, err := annotator.Annotations()
	c.Assert(err, gc.IsNil)
	c.Assert(annotations, gc.HasLen, 0)
	cons, err := s.State.EnvironConstraints()
	c.Assert(err, gc.IsNil)
	c.Assert(&cons, jc.Satisfies, constraints.IsEmpty)

	addrs, err := s.State.APIHostPorts()
	c.Assert(err, gc.IsNil)
	c.Assert(addrs, gc.HasLen, 0)

	info, err := s.State.StateServerInfo()
	c.Assert(err, gc.IsNil)
	c.Assert(info, jc.DeepEquals, &state.StateServerInfo{})
}
Example #5
0
func (s *InitializeSuite) TestEnvironConfigWithoutAgentVersion(c *gc.C) {
	// admin-secret blocks Initialize.
	good := testing.EnvironConfig(c)
	attrs := good.AllAttrs()
	delete(attrs, "agent-version")
	bad, err := config.New(config.NoDefaults, attrs)
	c.Assert(err, jc.ErrorIsNil)
	owner := names.NewLocalUserTag("initialize-admin")

	_, err = state.Initialize(owner, statetesting.NewMongoInfo(), bad, statetesting.NewDialOpts(), state.Policy(nil))
	c.Assert(err, gc.ErrorMatches, "agent-version must always be set in state")

	st := statetesting.Initialize(c, owner, good, nil)
	// yay side effects
	st.Close()

	s.openState(c, st.EnvironTag())
	err = s.State.UpdateEnvironConfig(map[string]interface{}{}, []string{"agent-version"}, nil)
	c.Assert(err, gc.ErrorMatches, "agent-version must always be set in state")

	// EnvironConfig remains inviolate.
	cfg, err := s.State.EnvironConfig()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(cfg.AllAttrs(), gc.DeepEquals, good.AllAttrs())
}
Example #6
0
// InitializeState should be called on the bootstrap machine's agent
// configuration. It uses that information to create the state server, dial the
// state server, and initialize it. It also generates a new password for the
// bootstrap machine and calls Write to save the the configuration.
//
// The envCfg values will be stored in the state's EnvironConfig; the
// machineCfg values will be used to configure the bootstrap Machine,
// and its constraints will be also be used for the environment-level
// constraints. The connection to the state server will respect the
// given timeout parameter.
//
// InitializeState returns the newly initialized state and bootstrap
// machine. If it fails, the state may well be irredeemably compromised.
func InitializeState(adminUser names.UserTag, c ConfigSetter, envCfg *config.Config, machineCfg BootstrapMachineConfig, dialOpts mongo.DialOpts, policy state.Policy) (_ *state.State, _ *state.Machine, resultErr error) {
	if c.Tag() != names.NewMachineTag(BootstrapMachineId) {
		return nil, nil, errors.Errorf("InitializeState not called with bootstrap machine's configuration")
	}
	servingInfo, ok := c.StateServingInfo()
	if !ok {
		return nil, nil, errors.Errorf("state serving information not available")
	}
	// N.B. no users are set up when we're initializing the state,
	// so don't use any tag or password when opening it.
	info, ok := c.MongoInfo()
	if !ok {
		return nil, nil, errors.Errorf("stateinfo not available")
	}
	info.Tag = nil
	info.Password = c.OldPassword()

	if err := initMongoAdminUser(info.Info, dialOpts, info.Password); err != nil {
		return nil, nil, errors.Annotate(err, "failed to initialize mongo admin user")
	}

	logger.Debugf("initializing address %v", info.Addrs)
	st, err := state.Initialize(adminUser, info, envCfg, dialOpts, policy)
	if err != nil {
		return nil, nil, errors.Errorf("failed to initialize state: %v", err)
	}
	logger.Debugf("connected to initial state")
	defer func() {
		if resultErr != nil {
			st.Close()
		}
	}()
	servingInfo.SharedSecret = machineCfg.SharedSecret
	c.SetStateServingInfo(servingInfo)

	// Filter out any LXC bridge addresses from the machine addresses,
	// except for local environments. See LP bug #1416928.
	if !isLocalEnv(envCfg) {
		machineCfg.Addresses = network.FilterLXCAddresses(machineCfg.Addresses)
	} else {
		logger.Debugf("local environment - not filtering addresses from %v", machineCfg.Addresses)
	}

	if err = initAPIHostPorts(c, st, machineCfg.Addresses, servingInfo.APIPort); err != nil {
		return nil, nil, err
	}
	ssi := paramsStateServingInfoToStateStateServingInfo(servingInfo)
	if err := st.SetStateServingInfo(ssi); err != nil {
		return nil, nil, errors.Errorf("cannot set state serving info: %v", err)
	}
	m, err := initConstraintsAndBootstrapMachine(c, st, machineCfg)
	if err != nil {
		return nil, nil, err
	}
	return st, m, nil
}
Example #7
0
func (s *InitializeSuite) TestInitializeWithCloudRegionConfig(c *gc.C) {
	cfg := testing.ModelConfig(c)
	uuid := cfg.UUID()

	// Phony region-config
	regionInheritedConfigIn := cloud.RegionConfig{
		"a-region": cloud.Attrs{
			"a-key": "a-value",
		},
		"b-region": cloud.Attrs{
			"b-key": "b-value",
		},
	}
	owner := names.NewLocalUserTag("initialize-admin")
	controllerCfg := testing.FakeControllerConfig()

	st, err := state.Initialize(state.InitializeParams{
		Clock:            clock.WallClock,
		ControllerConfig: controllerCfg,
		ControllerModelArgs: state.ModelArgs{
			CloudName:               "dummy",
			Owner:                   owner,
			Config:                  cfg,
			StorageProviderRegistry: storage.StaticProviderRegistry{},
		},
		CloudName: "dummy",
		Cloud: cloud.Cloud{
			Type:         "dummy",
			AuthTypes:    []cloud.AuthType{cloud.EmptyAuthType},
			RegionConfig: regionInheritedConfigIn, // Init with phony region-config
		},
		MongoInfo:     statetesting.NewMongoInfo(),
		MongoDialOpts: mongotest.DialOpts(),
	})
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(st, gc.NotNil)
	modelTag := st.ModelTag()
	c.Assert(modelTag.Id(), gc.Equals, uuid)
	err = st.Close()
	c.Assert(err, jc.ErrorIsNil)

	s.openState(c, modelTag)

	for k := range regionInheritedConfigIn {
		// Query for config for each region
		regionInheritedConfig, err := state.ReadSettings(
			s.State, state.GlobalSettingsC,
			"dummy#"+k)
		c.Assert(err, jc.ErrorIsNil)
		c.Assert(
			cloud.Attrs(regionInheritedConfig.Map()),
			jc.DeepEquals,
			regionInheritedConfigIn[k])
	}
}
Example #8
0
func (s *InitializeSuite) TestInitializeWithCloudRegionHits(c *gc.C) {
	cfg := testing.ModelConfig(c)
	uuid := cfg.UUID()

	controllerInheritedConfigIn := map[string]interface{}{
		"no-proxy": "local",
	}
	// Phony region-config
	regionInheritedConfigIn := cloud.RegionConfig{
		"a-region": cloud.Attrs{
			"no-proxy": "a-value",
		},
		"b-region": cloud.Attrs{
			"no-proxy": "b-value",
		},
	}
	owner := names.NewLocalUserTag("initialize-admin")
	controllerCfg := testing.FakeControllerConfig()

	st, err := state.Initialize(state.InitializeParams{
		Clock:            clock.WallClock,
		ControllerConfig: controllerCfg,
		ControllerModelArgs: state.ModelArgs{
			CloudName:               "dummy",
			Owner:                   owner,
			Config:                  cfg,
			StorageProviderRegistry: storage.StaticProviderRegistry{},
		},
		CloudName: "dummy",
		Cloud: cloud.Cloud{
			Type:         "dummy",
			AuthTypes:    []cloud.AuthType{cloud.EmptyAuthType},
			RegionConfig: regionInheritedConfigIn, // Init with phony region-config
		},
		ControllerInheritedConfig: controllerInheritedConfigIn,
		MongoInfo:                 statetesting.NewMongoInfo(),
		MongoDialOpts:             mongotest.DialOpts(),
	})
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(st, gc.NotNil)
	modelTag := st.ModelTag()
	c.Assert(modelTag.Id(), gc.Equals, uuid)
	err = st.Close()
	c.Assert(err, jc.ErrorIsNil)

	s.openState(c, modelTag)

	var attrs map[string]interface{}
	for r := range regionInheritedConfigIn {
		rspec := &environs.RegionSpec{Cloud: "dummy", Region: r}
		got, err := s.State.ComposeNewModelConfig(attrs, rspec)
		c.Check(err, jc.ErrorIsNil)
		c.Assert(got["no-proxy"], gc.Equals, regionInheritedConfigIn[r]["no-proxy"])
	}
}
Example #9
0
// Initialize initializes the state and returns it. If state was not
// already initialized, and cfg is nil, the minimal default model
// configuration will be used.
func Initialize(c *gc.C, owner names.UserTag, cfg *config.Config, policy state.Policy) *state.State {
	if cfg == nil {
		cfg = testing.ModelConfig(c)
	}
	mgoInfo := NewMongoInfo()
	dialOpts := NewDialOpts()

	st, err := state.Initialize(owner, mgoInfo, cfg, dialOpts, policy)
	c.Assert(err, jc.ErrorIsNil)
	return st
}
Example #10
0
func (s *InitializeSuite) TestInitializeWithControllerInheritedConfig(c *gc.C) {
	cfg := testing.ModelConfig(c)
	uuid := cfg.UUID()
	initial := cfg.AllAttrs()
	controllerInheritedConfigIn := map[string]interface{}{
		"default-series": initial["default-series"],
	}
	owner := names.NewLocalUserTag("initialize-admin")
	controllerCfg := testing.FakeControllerConfig()

	st, err := state.Initialize(state.InitializeParams{
		Clock:            clock.WallClock,
		ControllerConfig: controllerCfg,
		ControllerModelArgs: state.ModelArgs{
			CloudName:               "dummy",
			Owner:                   owner,
			Config:                  cfg,
			StorageProviderRegistry: storage.StaticProviderRegistry{},
		},
		CloudName: "dummy",
		Cloud: cloud.Cloud{
			Type:      "dummy",
			AuthTypes: []cloud.AuthType{cloud.EmptyAuthType},
		},
		ControllerInheritedConfig: controllerInheritedConfigIn,
		MongoInfo:                 statetesting.NewMongoInfo(),
		MongoDialOpts:             mongotest.DialOpts(),
	})
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(st, gc.NotNil)
	modelTag := st.ModelTag()
	c.Assert(modelTag.Id(), gc.Equals, uuid)
	err = st.Close()
	c.Assert(err, jc.ErrorIsNil)

	s.openState(c, modelTag)

	controllerInheritedConfig, err := state.ReadSettings(s.State, state.GlobalSettingsC, state.ControllerInheritedSettingsGlobalKey)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(controllerInheritedConfig.Map(), jc.DeepEquals, controllerInheritedConfigIn)

	expected := cfg.AllAttrs()
	for k, v := range config.ConfigDefaults() {
		if _, ok := expected[k]; !ok {
			expected[k] = v
		}
	}
	// Config as read from state has resources tags coerced to a map.
	expected["resource-tags"] = map[string]string{}
	cfg, err = s.State.ModelConfig()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(cfg.AllAttrs(), jc.DeepEquals, expected)
}
Example #11
0
func (s *InitializeSuite) TestInitialize(c *gc.C) {
	cfg := testing.EnvironConfig(c)
	uuid, _ := cfg.UUID()
	initial := cfg.AllAttrs()
	st, err := state.Initialize(state.TestingMongoInfo(), cfg, state.TestingDialOpts(), nil)
	c.Assert(err, gc.IsNil)
	c.Assert(st, gc.NotNil)
	envTag := st.EnvironTag()
	c.Assert(envTag.Id(), gc.Equals, uuid)
	err = st.Close()
	c.Assert(err, gc.IsNil)

	s.openState(c)

	cfg, err = s.State.EnvironConfig()
	c.Assert(err, gc.IsNil)
	c.Assert(cfg.AllAttrs(), gc.DeepEquals, initial)
	// Check that the environment has been created.
	env, err := s.State.Environment()
	c.Assert(err, gc.IsNil)
	c.Assert(env.Tag(), gc.Equals, envTag)
	// Check that the owner has been created.
	owner := names.NewLocalUserTag("admin")
	c.Assert(env.Owner(), gc.Equals, owner)
	// Check that the owner can be retrieved by the tag.
	entity, err := s.State.FindEntity(env.Owner())
	c.Assert(err, gc.IsNil)
	c.Assert(entity.Tag(), gc.Equals, owner)
	// Check that the owner has an EnvUser created for the bootstrapped environment.
	envUser, err := s.State.EnvironmentUser(env.Owner())
	c.Assert(err, gc.IsNil)
	c.Assert(envUser.UserTag().Username(), gc.Equals, env.Owner().Username())
	c.Assert(envUser.EnvironmentTag(), gc.Equals, env.Tag())

	// Check that the environment can be found through the tag.
	entity, err = s.State.FindEntity(envTag)
	c.Assert(err, gc.IsNil)
	annotator := entity.(state.Annotator)
	annotations, err := annotator.Annotations()
	c.Assert(err, gc.IsNil)
	c.Assert(annotations, gc.HasLen, 0)
	cons, err := s.State.EnvironConstraints()
	c.Assert(err, gc.IsNil)
	c.Assert(&cons, jc.Satisfies, constraints.IsEmpty)

	addrs, err := s.State.APIHostPorts()
	c.Assert(err, gc.IsNil)
	c.Assert(addrs, gc.HasLen, 0)

	info, err := s.State.StateServerInfo()
	c.Assert(err, gc.IsNil)
	c.Assert(info, jc.DeepEquals, &state.StateServerInfo{EnvironmentTag: envTag})
}
Example #12
0
File: conn.go Project: bac/juju
// InitializeWithArgs initializes the state and returns it. If state was not
// already initialized, and args.Config is nil, the minimal default model
// configuration will be used.
func InitializeWithArgs(c *gc.C, args InitializeArgs) *state.State {
	if args.InitialConfig == nil {
		args.InitialConfig = testing.ModelConfig(c)
	}
	mgoInfo := NewMongoInfo()
	dialOpts := mongotest.DialOpts()

	controllerCfg := testing.FakeControllerConfig()
	st, err := state.Initialize(state.InitializeParams{
		Clock:            args.Clock,
		ControllerConfig: controllerCfg,
		ControllerModelArgs: state.ModelArgs{
			CloudName:   "dummy",
			CloudRegion: "dummy-region",
			Config:      args.InitialConfig,
			Owner:       args.Owner,
			StorageProviderRegistry: StorageProviders(),
		},
		ControllerInheritedConfig: args.ControllerInheritedConfig,
		CloudName:                 "dummy",
		Cloud: cloud.Cloud{
			Type:      "dummy",
			AuthTypes: []cloud.AuthType{cloud.EmptyAuthType},
			Regions: []cloud.Region{
				cloud.Region{
					Name:             "dummy-region",
					Endpoint:         "dummy-endpoint",
					IdentityEndpoint: "dummy-identity-endpoint",
					StorageEndpoint:  "dummy-storage-endpoint",
				},
				cloud.Region{
					Name:             "nether-region",
					Endpoint:         "nether-endpoint",
					IdentityEndpoint: "nether-identity-endpoint",
					StorageEndpoint:  "nether-storage-endpoint",
				},
				cloud.Region{
					Name:             "unused-region",
					Endpoint:         "unused-endpoint",
					IdentityEndpoint: "unused-identity-endpoint",
					StorageEndpoint:  "unused-storage-endpoint",
				},
			},
			RegionConfig: args.RegionConfig,
		},
		MongoInfo:     mgoInfo,
		MongoDialOpts: dialOpts,
		NewPolicy:     args.NewPolicy,
	})
	c.Assert(err, jc.ErrorIsNil)
	return st
}
Example #13
0
func (s *InitializeSuite) TestDoubleInitializeConfig(c *gc.C) {
	cfg := testing.ModelConfig(c)
	owner := names.NewLocalUserTag("initialize-admin")

	mgoInfo := statetesting.NewMongoInfo()
	dialOpts := mongotest.DialOpts()
	controllerCfg := testing.FakeControllerConfig()

	args := state.InitializeParams{
		Clock:            clock.WallClock,
		ControllerConfig: controllerCfg,
		ControllerModelArgs: state.ModelArgs{
			CloudName:               "dummy",
			Owner:                   owner,
			Config:                  cfg,
			StorageProviderRegistry: storage.StaticProviderRegistry{},
		},
		CloudName: "dummy",
		Cloud: cloud.Cloud{
			Type:      "dummy",
			AuthTypes: []cloud.AuthType{cloud.EmptyAuthType},
		},
		MongoInfo:     mgoInfo,
		MongoDialOpts: dialOpts,
	}
	st, err := state.Initialize(args)
	c.Assert(err, jc.ErrorIsNil)
	err = st.Close()
	c.Check(err, jc.ErrorIsNil)

	st, err = state.Initialize(args)
	c.Check(err, gc.ErrorMatches, "already initialized")
	if !c.Check(st, gc.IsNil) {
		err = st.Close()
		c.Check(err, jc.ErrorIsNil)
	}
}
Example #14
0
func (s *InitializeSuite) TestInitialize(c *gc.C) {
	cfg := testing.ModelConfig(c)
	uuid, _ := cfg.UUID()
	initial := cfg.AllAttrs()
	owner := names.NewLocalUserTag("initialize-admin")
	st, err := state.Initialize(owner, statetesting.NewMongoInfo(), cfg, statetesting.NewDialOpts(), nil)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(st, gc.NotNil)
	modelTag := st.ModelTag()
	c.Assert(modelTag.Id(), gc.Equals, uuid)
	err = st.Close()
	c.Assert(err, jc.ErrorIsNil)

	s.openState(c, modelTag)

	cfg, err = s.State.ModelConfig()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(cfg.AllAttrs(), gc.DeepEquals, initial)
	// Check that the model has been created.
	env, err := s.State.Model()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(env.Tag(), gc.Equals, modelTag)
	// Check that the owner has been created.
	c.Assert(env.Owner(), gc.Equals, owner)
	// Check that the owner can be retrieved by the tag.
	entity, err := s.State.FindEntity(env.Owner())
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(entity.Tag(), gc.Equals, owner)
	// Check that the owner has an ModelUser created for the bootstrapped model.
	modelUser, err := s.State.ModelUser(env.Owner())
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(modelUser.UserTag(), gc.Equals, owner)
	c.Assert(modelUser.ModelTag(), gc.Equals, env.Tag())

	// Check that the model can be found through the tag.
	entity, err = s.State.FindEntity(modelTag)
	c.Assert(err, jc.ErrorIsNil)
	cons, err := s.State.ModelConstraints()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(&cons, jc.Satisfies, constraints.IsEmpty)

	addrs, err := s.State.APIHostPorts()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(addrs, gc.HasLen, 0)

	info, err := s.State.StateServerInfo()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(info, jc.DeepEquals, &state.StateServerInfo{ModelTag: modelTag})
}
Example #15
0
func InitializeState(c ConfigSetter, envCfg *config.Config, machineCfg BootstrapMachineConfig, dialOpts mongo.DialOpts, policy state.Policy) (_ *state.State, _ *state.Machine, resultErr error) {
	if c.Tag() != names.NewMachineTag(BootstrapMachineId) {
		return nil, nil, fmt.Errorf("InitializeState not called with bootstrap machine's configuration")
	}
	servingInfo, ok := c.StateServingInfo()
	if !ok {
		return nil, nil, fmt.Errorf("state serving information not available")
	}
	// N.B. no users are set up when we're initializing the state,
	// so don't use any tag or password when opening it.
	info, ok := c.MongoInfo()
	if !ok {
		return nil, nil, fmt.Errorf("stateinfo not available")
	}
	info.Tag = nil
	info.Password = c.OldPassword()

	if err := initMongoAdminUser(info.Info, dialOpts, info.Password); err != nil {
		return nil, nil, errors.Annotate(err, "failed to initialize mongo admin user")
	}

	logger.Debugf("initializing address %v", info.Addrs)
	st, err := state.Initialize(info, envCfg, dialOpts, policy)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to initialize state: %v", err)
	}
	logger.Debugf("connected to initial state")
	defer func() {
		if resultErr != nil {
			st.Close()
		}
	}()
	servingInfo.SharedSecret = machineCfg.SharedSecret
	c.SetStateServingInfo(servingInfo)
	if err = initAPIHostPorts(c, st, machineCfg.Addresses, servingInfo.APIPort); err != nil {
		return nil, nil, err
	}
	if err := st.SetStateServingInfo(servingInfo); err != nil {
		return nil, nil, fmt.Errorf("cannot set state serving info: %v", err)
	}
	m, err := initUsersAndBootstrapMachine(c, st, machineCfg)
	if err != nil {
		return nil, nil, err
	}
	return st, m, nil
}
Example #16
0
File: conn.go Project: kat-co/juju
// Initialize initializes the state and returns it. If state was not
// already initialized, and cfg is nil, the minimal default model
// configuration will be used.
func Initialize(c *gc.C, owner names.UserTag, cfg *config.Config, controllerInheritedConfig map[string]interface{}, regionConfig cloud.RegionConfig, newPolicy state.NewPolicyFunc) *state.State {
	if cfg == nil {
		cfg = testing.ModelConfig(c)
	}
	mgoInfo := NewMongoInfo()
	dialOpts := mongotest.DialOpts()

	controllerCfg := testing.FakeControllerConfig()
	st, err := state.Initialize(state.InitializeParams{
		Clock:            clock.WallClock,
		ControllerConfig: controllerCfg,
		ControllerModelArgs: state.ModelArgs{
			CloudName:   "dummy",
			CloudRegion: "dummy-region",
			Config:      cfg,
			Owner:       owner,
			StorageProviderRegistry: StorageProviders(),
		},
		ControllerInheritedConfig: controllerInheritedConfig,
		CloudName:                 "dummy",
		Cloud: cloud.Cloud{
			Type:      "dummy",
			AuthTypes: []cloud.AuthType{cloud.EmptyAuthType},
			Regions: []cloud.Region{
				cloud.Region{
					Name:             "dummy-region",
					Endpoint:         "dummy-endpoint",
					IdentityEndpoint: "dummy-identity-endpoint",
					StorageEndpoint:  "dummy-storage-endpoint",
				},
				cloud.Region{
					Name:             "nether-region",
					Endpoint:         "nether-endpoint",
					IdentityEndpoint: "nether-identity-endpoint",
					StorageEndpoint:  "nether-storage-endpoint",
				},
			},
			RegionConfig: regionConfig,
		},
		MongoInfo:     mgoInfo,
		MongoDialOpts: dialOpts,
		NewPolicy:     newPolicy,
	})
	c.Assert(err, jc.ErrorIsNil)
	return st
}
Example #17
0
func (s *ModelCloudValidationSuite) initializeState(
	c *gc.C,
	regions []cloud.Region,
	authTypes []cloud.AuthType,
	credentials map[names.CloudCredentialTag]cloud.Credential,
) (*state.State, names.UserTag) {
	owner := names.NewUserTag("test@remote")
	cfg, _ := createTestModelConfig(c, "")
	var controllerRegion string
	var controllerCredential names.CloudCredentialTag
	if len(regions) > 0 {
		controllerRegion = regions[0].Name
	}
	if len(credentials) > 0 {
		// pick an arbitrary credential
		for controllerCredential = range credentials {
		}
	}
	controllerCfg := testing.FakeControllerConfig()
	st, err := state.Initialize(state.InitializeParams{
		Clock:            clock.WallClock,
		ControllerConfig: controllerCfg,
		ControllerModelArgs: state.ModelArgs{
			Owner:                   owner,
			Config:                  cfg,
			CloudName:               "dummy",
			CloudRegion:             controllerRegion,
			CloudCredential:         controllerCredential,
			StorageProviderRegistry: storage.StaticProviderRegistry{},
		},
		CloudName: "dummy",
		Cloud: cloud.Cloud{
			Type:      "dummy",
			AuthTypes: authTypes,
			Regions:   regions,
		},
		CloudCredentials: credentials,
		MongoInfo:        statetesting.NewMongoInfo(),
		MongoDialOpts:    mongotest.DialOpts(),
	})
	c.Assert(err, jc.ErrorIsNil)
	return st, owner
}
Example #18
0
func (s *factorySuite) SetUpTest(c *gc.C) {
	s.BaseSuite.SetUpTest(c)
	s.MgoSuite.SetUpTest(c)
	policy := statetesting.MockPolicy{}

	info := &state.Info{
		Info: mongo.Info{
			Addrs:  []string{jtesting.MgoServer.Addr()},
			CACert: testing.CACert,
		},
	}
	opts := mongo.DialOpts{
		Timeout: testing.LongWait,
	}
	cfg := testing.EnvironConfig(c)
	st, err := state.Initialize(info, cfg, opts, &policy)
	c.Assert(err, gc.IsNil)
	s.State = st
	s.Factory = factory.NewFactory(s.State, c)
}
Example #19
0
func (s *InitializeSuite) TestDoubleInitializeConfig(c *gc.C) {
	cfg := testing.EnvironConfig(c)
	initial := cfg.AllAttrs()
	st := TestingInitialize(c, cfg, nil)
	st.Close()

	// A second initialize returns an open *State, but ignores its params.
	// TODO(fwereade) I think this is crazy, but it's what we were testing
	// for originally...
	cfg, err := cfg.Apply(map[string]interface{}{"authorized-keys": "something-else"})
	c.Assert(err, gc.IsNil)
	st, err = state.Initialize(state.TestingMongoInfo(), cfg, state.TestingDialOpts(), state.Policy(nil))
	c.Assert(err, gc.IsNil)
	c.Assert(st, gc.NotNil)
	st.Close()

	s.openState(c)
	cfg, err = s.State.EnvironConfig()
	c.Assert(err, gc.IsNil)
	c.Assert(cfg.AllAttrs(), gc.DeepEquals, initial)
}
Example #20
0
func (s *InitializeSuite) TestEnvironConfigWithAdminSecret(c *gc.C) {
	// admin-secret blocks Initialize.
	good := testing.EnvironConfig(c)
	badUpdateAttrs := map[string]interface{}{"admin-secret": "foo"}
	bad, err := good.Apply(badUpdateAttrs)

	_, err = state.Initialize(state.TestingMongoInfo(), bad, state.TestingDialOpts(), state.Policy(nil))
	c.Assert(err, gc.ErrorMatches, "admin-secret should never be written to the state")

	// admin-secret blocks UpdateEnvironConfig.
	st := TestingInitialize(c, good, nil)
	st.Close()

	s.openState(c)
	err = s.State.UpdateEnvironConfig(badUpdateAttrs, nil, nil)
	c.Assert(err, gc.ErrorMatches, "admin-secret should never be written to the state")

	// EnvironConfig remains inviolate.
	cfg, err := s.State.EnvironConfig()
	c.Assert(err, gc.IsNil)
	c.Assert(cfg.AllAttrs(), gc.DeepEquals, good.AllAttrs())
}
Example #21
0
func (s *InitializeSuite) TestModelConfigWithAdminSecret(c *gc.C) {
	// admin-secret blocks Initialize.
	good := testing.ModelConfig(c)
	badUpdateAttrs := map[string]interface{}{"admin-secret": "foo"}
	bad, err := good.Apply(badUpdateAttrs)
	owner := names.NewLocalUserTag("initialize-admin")

	_, err = state.Initialize(owner, statetesting.NewMongoInfo(), bad, statetesting.NewDialOpts(), state.Policy(nil))
	c.Assert(err, gc.ErrorMatches, "admin-secret should never be written to the state")

	// admin-secret blocks UpdateModelConfig.
	st := statetesting.Initialize(c, owner, good, nil)
	st.Close()

	s.openState(c, st.ModelTag())
	err = s.State.UpdateModelConfig(badUpdateAttrs, nil, nil)
	c.Assert(err, gc.ErrorMatches, "admin-secret should never be written to the state")

	// ModelConfig remains inviolate.
	cfg, err := s.State.ModelConfig()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(cfg.AllAttrs(), gc.DeepEquals, good.AllAttrs())
}
Example #22
0
func (s *InitializeSuite) TestCloudConfigWithForbiddenValues(c *gc.C) {
	badAttrNames := []string{
		"admin-secret",
		"ca-private-key",
		config.AgentVersionKey,
	}
	for _, attr := range controller.ControllerOnlyConfigAttributes {
		badAttrNames = append(badAttrNames, attr)
	}

	modelCfg := testing.ModelConfig(c)
	controllerCfg := testing.FakeControllerConfig()
	args := state.InitializeParams{
		Clock:            clock.WallClock,
		ControllerConfig: controllerCfg,
		ControllerModelArgs: state.ModelArgs{
			CloudName:               "dummy",
			Owner:                   names.NewLocalUserTag("initialize-admin"),
			Config:                  modelCfg,
			StorageProviderRegistry: storage.StaticProviderRegistry{},
		},
		CloudName: "dummy",
		Cloud: cloud.Cloud{
			Type:      "dummy",
			AuthTypes: []cloud.AuthType{cloud.EmptyAuthType},
		},
		MongoInfo:     statetesting.NewMongoInfo(),
		MongoDialOpts: mongotest.DialOpts(),
	}

	for _, badAttrName := range badAttrNames {
		badAttrs := map[string]interface{}{badAttrName: "foo"}
		args.ControllerInheritedConfig = badAttrs
		_, err := state.Initialize(args)
		c.Assert(err, gc.ErrorMatches, "local cloud config cannot contain .*")
	}
}
Example #23
0
func (e *environ) Bootstrap(ctx environs.BootstrapContext, args environs.BootstrapParams) error {
	selectedTools, err := common.EnsureBootstrapTools(ctx, e, config.PreferredSeries(e.Config()), args.Constraints.Arch)
	if err != nil {
		return err
	}
	series := selectedTools.OneSeries()

	defer delay()
	if err := e.checkBroken("Bootstrap"); err != nil {
		return err
	}
	network.InitializeFromConfig(e.Config())
	password := e.Config().AdminSecret()
	if password == "" {
		return fmt.Errorf("admin-secret is required for bootstrap")
	}
	if _, ok := e.Config().CACert(); !ok {
		return fmt.Errorf("no CA certificate in environment configuration")
	}

	logger.Infof("would pick tools from %s", selectedTools)
	cfg, err := environs.BootstrapConfig(e.Config())
	if err != nil {
		return fmt.Errorf("cannot make bootstrap config: %v", err)
	}

	estate, err := e.state()
	if err != nil {
		return err
	}
	estate.mu.Lock()
	defer estate.mu.Unlock()
	if estate.bootstrapped {
		return fmt.Errorf("environment is already bootstrapped")
	}
	estate.preferIPv6 = e.Config().PreferIPv6()

	// Write the bootstrap file just like a normal provider. However
	// we need to release the mutex for the save state to work, so regain
	// it after the call.
	estate.mu.Unlock()
	instIds := []instance.Id{BootstrapInstanceId}
	if err := bootstrap.SaveState(e.Storage(), &bootstrap.BootstrapState{StateInstances: instIds}); err != nil {
		logger.Errorf("failed to save state instances: %v", err)
		estate.mu.Lock() // otherwise defered unlock will fail
		return err
	}
	estate.mu.Lock() // back at it

	// Create an instance for the bootstrap node.
	logger.Infof("creating bootstrap instance")
	i := &dummyInstance{
		id:           BootstrapInstanceId,
		addresses:    network.NewAddresses("localhost"),
		ports:        make(map[network.Port]bool),
		machineId:    agent.BootstrapMachineId,
		series:       series,
		firewallMode: e.Config().FirewallMode(),
		state:        estate,
		stateServer:  true,
	}
	estate.insts[i.id] = i

	if e.ecfg().stateServer() {
		// TODO(rog) factor out relevant code from cmd/jujud/bootstrap.go
		// so that we can call it here.

		info := stateInfo(estate.preferIPv6)
		st, err := state.Initialize(info, cfg, mongo.DefaultDialOpts(), estate.statePolicy)
		if err != nil {
			panic(err)
		}
		if err := st.SetEnvironConstraints(args.Constraints); err != nil {
			panic(err)
		}
		if err := st.SetAdminMongoPassword(utils.UserPasswordHash(password, utils.CompatSalt)); err != nil {
			panic(err)
		}
		_, err = st.AddAdminUser(password)
		if err != nil {
			panic(err)
		}
		estate.apiServer, err = apiserver.NewServer(st, estate.apiListener, apiserver.ServerConfig{
			Cert:    []byte(testing.ServerCert),
			Key:     []byte(testing.ServerKey),
			DataDir: DataDir,
			LogDir:  LogDir,
		})
		if err != nil {
			panic(err)
		}
		estate.apiState = st
	}
	estate.bootstrapped = true
	estate.ops <- OpBootstrap{Context: ctx, Env: e.name, Args: args}
	return nil
}
Example #24
0
File: environs.go Project: bac/juju
func (e *environ) Bootstrap(ctx environs.BootstrapContext, args environs.BootstrapParams) (*environs.BootstrapResult, error) {
	series := config.PreferredSeries(e.Config())
	availableTools, err := args.AvailableTools.Match(coretools.Filter{Series: series})
	if err != nil {
		return nil, err
	}
	arch := availableTools.Arches()[0]

	defer delay()
	if err := e.checkBroken("Bootstrap"); err != nil {
		return nil, err
	}
	if _, ok := args.ControllerConfig.CACert(); !ok {
		return nil, errors.New("no CA certificate in controller configuration")
	}

	logger.Infof("would pick tools from %s", availableTools)

	estate, err := e.state()
	if err != nil {
		return nil, err
	}
	estate.mu.Lock()
	defer estate.mu.Unlock()
	if estate.bootstrapped {
		return nil, errors.New("model is already bootstrapped")
	}

	// Create an instance for the bootstrap node.
	logger.Infof("creating bootstrap instance")
	i := &dummyInstance{
		id:           BootstrapInstanceId,
		addresses:    network.NewAddresses("localhost"),
		ports:        make(map[network.PortRange]bool),
		machineId:    agent.BootstrapMachineId,
		series:       series,
		firewallMode: e.Config().FirewallMode(),
		state:        estate,
		controller:   true,
	}
	estate.insts[i.id] = i
	estate.bootstrapped = true
	estate.ops <- OpBootstrap{Context: ctx, Env: e.name, Args: args}

	finalize := func(ctx environs.BootstrapContext, icfg *instancecfg.InstanceConfig, _ environs.BootstrapDialOpts) error {
		if e.ecfg().controller() {
			icfg.Bootstrap.BootstrapMachineInstanceId = BootstrapInstanceId
			if err := instancecfg.FinishInstanceConfig(icfg, e.Config()); err != nil {
				return err
			}

			adminUser := names.NewUserTag("admin@local")
			var cloudCredentialTag names.CloudCredentialTag
			if icfg.Bootstrap.ControllerCloudCredentialName != "" {
				cloudCredentialTag = names.NewCloudCredentialTag(fmt.Sprintf(
					"%s/%s/%s",
					icfg.Bootstrap.ControllerCloudName,
					adminUser.Id(),
					icfg.Bootstrap.ControllerCloudCredentialName,
				))
			}

			cloudCredentials := make(map[names.CloudCredentialTag]cloud.Credential)
			if icfg.Bootstrap.ControllerCloudCredential != nil && icfg.Bootstrap.ControllerCloudCredentialName != "" {
				cloudCredentials[cloudCredentialTag] = *icfg.Bootstrap.ControllerCloudCredential
			}

			info := stateInfo()
			// Since the admin user isn't setup until after here,
			// the password in the info structure is empty, so the admin
			// user is constructed with an empty password here.
			// It is set just below.
			st, err := state.Initialize(state.InitializeParams{
				Clock:            clock.WallClock,
				ControllerConfig: icfg.Controller.Config,
				ControllerModelArgs: state.ModelArgs{
					Owner:                   adminUser,
					Config:                  icfg.Bootstrap.ControllerModelConfig,
					Constraints:             icfg.Bootstrap.BootstrapMachineConstraints,
					CloudName:               icfg.Bootstrap.ControllerCloudName,
					CloudRegion:             icfg.Bootstrap.ControllerCloudRegion,
					CloudCredential:         cloudCredentialTag,
					StorageProviderRegistry: e,
				},
				Cloud:            icfg.Bootstrap.ControllerCloud,
				CloudName:        icfg.Bootstrap.ControllerCloudName,
				CloudCredentials: cloudCredentials,
				MongoInfo:        info,
				MongoDialOpts:    mongotest.DialOpts(),
				NewPolicy:        estate.newStatePolicy,
			})
			if err != nil {
				return err
			}
			if err := st.SetModelConstraints(args.ModelConstraints); err != nil {
				return err
			}
			if err := st.SetAdminMongoPassword(icfg.Controller.MongoInfo.Password); err != nil {
				return err
			}
			if err := st.MongoSession().DB("admin").Login("admin", icfg.Controller.MongoInfo.Password); err != nil {
				return err
			}
			env, err := st.Model()
			if err != nil {
				return err
			}
			owner, err := st.User(env.Owner())
			if err != nil {
				return err
			}
			// We log this out for test purposes only. No one in real life can use
			// a dummy provider for anything other than testing, so logging the password
			// here is fine.
			logger.Debugf("setting password for %q to %q", owner.Name(), icfg.Controller.MongoInfo.Password)
			owner.SetPassword(icfg.Controller.MongoInfo.Password)

			estate.apiStatePool = state.NewStatePool(st)

			estate.apiServer, err = apiserver.NewServer(st, estate.apiListener, apiserver.ServerConfig{
				Clock:       clock.WallClock,
				Cert:        testing.ServerCert,
				Key:         testing.ServerKey,
				Tag:         names.NewMachineTag("0"),
				DataDir:     DataDir,
				LogDir:      LogDir,
				StatePool:   estate.apiStatePool,
				NewObserver: func() observer.Observer { return &fakeobserver.Instance{} },
				// Should never be used but prevent external access just in case.
				AutocertURL: "https://0.1.2.3/no-autocert-here",
			})
			if err != nil {
				panic(err)
			}
			estate.apiState = st
		}
		estate.ops <- OpFinalizeBootstrap{Context: ctx, Env: e.name, InstanceConfig: icfg}
		return nil
	}

	bsResult := &environs.BootstrapResult{
		Arch:     arch,
		Series:   series,
		Finalize: finalize,
	}
	return bsResult, nil
}
Example #25
0
func (s *InitializeSuite) TestInitialize(c *gc.C) {
	cfg := testing.ModelConfig(c)
	uuid := cfg.UUID()
	owner := names.NewLocalUserTag("initialize-admin")

	userPassCredentialTag := names.NewCloudCredentialTag(
		"dummy/" + owner.Canonical() + "/some-credential",
	)
	emptyCredentialTag := names.NewCloudCredentialTag(
		"dummy/" + owner.Canonical() + "/empty-credential",
	)
	userpassCredential := cloud.NewCredential(
		cloud.UserPassAuthType,
		map[string]string{
			"username": "******",
			"password": "******",
		},
	)
	userpassCredential.Label = userPassCredentialTag.Name()
	emptyCredential := cloud.NewEmptyCredential()
	emptyCredential.Label = emptyCredentialTag.Name()
	cloudCredentialsIn := map[names.CloudCredentialTag]cloud.Credential{
		userPassCredentialTag: userpassCredential,
		emptyCredentialTag:    emptyCredential,
	}
	controllerCfg := testing.FakeControllerConfig()

	st, err := state.Initialize(state.InitializeParams{
		Clock:            clock.WallClock,
		ControllerConfig: controllerCfg,
		ControllerModelArgs: state.ModelArgs{
			Owner:                   owner,
			Config:                  cfg,
			CloudName:               "dummy",
			CloudRegion:             "dummy-region",
			CloudCredential:         userPassCredentialTag,
			StorageProviderRegistry: storage.StaticProviderRegistry{},
		},
		CloudName: "dummy",
		Cloud: cloud.Cloud{
			Type: "dummy",
			AuthTypes: []cloud.AuthType{
				cloud.EmptyAuthType, cloud.UserPassAuthType,
			},
			Regions: []cloud.Region{{Name: "dummy-region"}},
		},
		CloudCredentials: cloudCredentialsIn,
		MongoInfo:        statetesting.NewMongoInfo(),
		MongoDialOpts:    mongotest.DialOpts(),
	})
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(st, gc.NotNil)
	modelTag := st.ModelTag()
	c.Assert(modelTag.Id(), gc.Equals, uuid)
	err = st.Close()
	c.Assert(err, jc.ErrorIsNil)

	s.openState(c, modelTag)

	cfg, err = s.State.ModelConfig()
	c.Assert(err, jc.ErrorIsNil)
	expected := cfg.AllAttrs()
	for k, v := range config.ConfigDefaults() {
		if _, ok := expected[k]; !ok {
			expected[k] = v
		}
	}
	c.Assert(cfg.AllAttrs(), jc.DeepEquals, expected)
	// Check that the model has been created.
	model, err := s.State.Model()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(model.Tag(), gc.Equals, modelTag)
	c.Assert(model.CloudRegion(), gc.Equals, "dummy-region")
	// Check that the owner has been created.
	c.Assert(model.Owner(), gc.Equals, owner)
	// Check that the owner can be retrieved by the tag.
	entity, err := s.State.FindEntity(model.Owner())
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(entity.Tag(), gc.Equals, owner)
	// Check that the owner has an ModelUser created for the bootstrapped model.
	modelUser, err := s.State.UserAccess(model.Owner(), model.Tag())
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(modelUser.UserTag, gc.Equals, owner)
	c.Assert(modelUser.Object, gc.Equals, model.Tag())

	// Check that the model can be found through the tag.
	entity, err = s.State.FindEntity(modelTag)
	c.Assert(err, jc.ErrorIsNil)
	cons, err := s.State.ModelConstraints()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(&cons, jc.Satisfies, constraints.IsEmpty)

	addrs, err := s.State.APIHostPorts()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(addrs, gc.HasLen, 0)

	info, err := s.State.ControllerInfo()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(info, jc.DeepEquals, &state.ControllerInfo{ModelTag: modelTag, CloudName: "dummy"})

	// Check that the model's cloud and credential names are as
	// expected, and the owner's cloud credentials are initialised.
	c.Assert(model.Cloud(), gc.Equals, "dummy")
	credentialTag, ok := model.CloudCredential()
	c.Assert(ok, jc.IsTrue)
	c.Assert(credentialTag, gc.Equals, userPassCredentialTag)
	cloudCredentials, err := s.State.CloudCredentials(model.Owner(), "dummy")
	c.Assert(err, jc.ErrorIsNil)
	expectedCred := make(map[string]cloud.Credential, len(cloudCredentialsIn))
	for tag, cred := range cloudCredentialsIn {
		expectedCred[tag.Canonical()] = cred
	}
	c.Assert(cloudCredentials, jc.DeepEquals, expectedCred)
}
Example #26
0
// InitializeState should be called on the bootstrap machine's agent
// configuration. It uses that information to create the controller, dial the
// controller, and initialize it. It also generates a new password for the
// bootstrap machine and calls Write to save the the configuration.
//
// The cfg values will be stored in the state's ModelConfig; the
// machineCfg values will be used to configure the bootstrap Machine,
// and its constraints will be also be used for the model-level
// constraints. The connection to the controller will respect the
// given timeout parameter.
//
// InitializeState returns the newly initialized state and bootstrap
// machine. If it fails, the state may well be irredeemably compromised.
func InitializeState(
	adminUser names.UserTag,
	c agent.ConfigSetter,
	cfg *config.Config,
	hostedModelConfigAttrs map[string]interface{},
	machineCfg BootstrapMachineConfig,
	dialOpts mongo.DialOpts,
	policy state.Policy,
) (_ *state.State, _ *state.Machine, resultErr error) {
	if c.Tag() != names.NewMachineTag(agent.BootstrapMachineId) {
		return nil, nil, errors.Errorf("InitializeState not called with bootstrap machine's configuration")
	}
	servingInfo, ok := c.StateServingInfo()
	if !ok {
		return nil, nil, errors.Errorf("state serving information not available")
	}
	// N.B. no users are set up when we're initializing the state,
	// so don't use any tag or password when opening it.
	info, ok := c.MongoInfo()
	if !ok {
		return nil, nil, errors.Errorf("stateinfo not available")
	}
	info.Tag = nil
	info.Password = c.OldPassword()

	if err := initMongoAdminUser(info.Info, dialOpts, info.Password); err != nil {
		return nil, nil, errors.Annotate(err, "failed to initialize mongo admin user")
	}

	logger.Debugf("initializing address %v", info.Addrs)
	st, err := state.Initialize(adminUser, info, cfg, dialOpts, policy)
	if err != nil {
		return nil, nil, errors.Errorf("failed to initialize state: %v", err)
	}
	logger.Debugf("connected to initial state")
	defer func() {
		if resultErr != nil {
			st.Close()
		}
	}()
	servingInfo.SharedSecret = machineCfg.SharedSecret
	c.SetStateServingInfo(servingInfo)

	// Filter out any LXC bridge addresses from the machine addresses.
	machineCfg.Addresses = network.FilterLXCAddresses(machineCfg.Addresses)

	if err = initAPIHostPorts(c, st, machineCfg.Addresses, servingInfo.APIPort); err != nil {
		return nil, nil, err
	}
	ssi := paramsStateServingInfoToStateStateServingInfo(servingInfo)
	if err := st.SetStateServingInfo(ssi); err != nil {
		return nil, nil, errors.Errorf("cannot set state serving info: %v", err)
	}
	m, err := initConstraintsAndBootstrapMachine(c, st, machineCfg)
	if err != nil {
		return nil, nil, err
	}

	// Create the initial hosted model, with the model config passed to
	// bootstrap, which contains the UUID, name for the hosted model,
	// and any user supplied config.
	attrs := make(map[string]interface{})
	for k, v := range hostedModelConfigAttrs {
		attrs[k] = v
	}
	hostedModelConfig, err := modelmanager.ModelConfigCreator{}.NewModelConfig(modelmanager.IsAdmin, cfg, attrs)
	if err != nil {
		return nil, nil, errors.Annotate(err, "creating hosted model config")
	}
	_, hostedModelState, err := st.NewModel(hostedModelConfig, adminUser)
	if err != nil {
		return nil, nil, errors.Annotate(err, "creating hosted model")
	}
	if err := hostedModelState.SetModelConstraints(machineCfg.ModelConstraints); err != nil {
		return nil, nil, errors.Annotate(err, "cannot set initial hosted model constraints")
	}
	hostedModelState.Close()

	return st, m, nil
}
Example #27
0
func (e *environ) Bootstrap(ctx environs.BootstrapContext, args environs.BootstrapParams) (arch, series string, _ environs.BootstrapFinalizer, _ error) {
	series = config.PreferredSeries(e.Config())
	availableTools, err := args.AvailableTools.Match(coretools.Filter{Series: series})
	if err != nil {
		return "", "", nil, err
	}
	arch = availableTools.Arches()[0]

	defer delay()
	if err := e.checkBroken("Bootstrap"); err != nil {
		return "", "", nil, err
	}
	network.InitializeFromConfig(e.Config())
	password := e.Config().AdminSecret()
	if password == "" {
		return "", "", nil, fmt.Errorf("admin-secret is required for bootstrap")
	}
	if _, ok := e.Config().CACert(); !ok {
		return "", "", nil, fmt.Errorf("no CA certificate in environment configuration")
	}

	logger.Infof("would pick tools from %s", availableTools)
	cfg, err := environs.BootstrapConfig(e.Config())
	if err != nil {
		return "", "", nil, fmt.Errorf("cannot make bootstrap config: %v", err)
	}

	estate, err := e.state()
	if err != nil {
		return "", "", nil, err
	}
	estate.mu.Lock()
	defer estate.mu.Unlock()
	if estate.bootstrapped {
		return "", "", nil, fmt.Errorf("environment is already bootstrapped")
	}
	estate.preferIPv6 = e.Config().PreferIPv6()

	// Create an instance for the bootstrap node.
	logger.Infof("creating bootstrap instance")
	i := &dummyInstance{
		id:           BootstrapInstanceId,
		addresses:    network.NewAddresses("localhost"),
		ports:        make(map[network.PortRange]bool),
		machineId:    agent.BootstrapMachineId,
		series:       series,
		firewallMode: e.Config().FirewallMode(),
		state:        estate,
		stateServer:  true,
	}
	estate.insts[i.id] = i

	if e.ecfg().stateServer() {
		// TODO(rog) factor out relevant code from cmd/jujud/bootstrap.go
		// so that we can call it here.

		info := stateInfo(estate.preferIPv6)
		// Since the admin user isn't setup until after here,
		// the password in the info structure is empty, so the admin
		// user is constructed with an empty password here.
		// It is set just below.
		st, err := state.Initialize(
			AdminUserTag(), info, cfg,
			mongo.DefaultDialOpts(), estate.statePolicy)
		if err != nil {
			panic(err)
		}
		if err := st.SetEnvironConstraints(args.Constraints); err != nil {
			panic(err)
		}
		if err := st.SetAdminMongoPassword(password); err != nil {
			panic(err)
		}
		if err := st.MongoSession().DB("admin").Login("admin", password); err != nil {
			panic(err)
		}
		env, err := st.Environment()
		if err != nil {
			panic(err)
		}
		owner, err := st.User(env.Owner())
		if err != nil {
			panic(err)
		}
		// We log this out for test purposes only. No one in real life can use
		// a dummy provider for anything other than testing, so logging the password
		// here is fine.
		logger.Debugf("setting password for %q to %q", owner.Name(), password)
		owner.SetPassword(password)

		estate.apiServer, err = apiserver.NewServer(st, estate.apiListener, apiserver.ServerConfig{
			Cert:    []byte(testing.ServerCert),
			Key:     []byte(testing.ServerKey),
			Tag:     names.NewMachineTag("0"),
			DataDir: DataDir,
			LogDir:  LogDir,
		})
		if err != nil {
			panic(err)
		}
		estate.apiState = st
	}
	estate.bootstrapped = true
	estate.ops <- OpBootstrap{Context: ctx, Env: e.name, Args: args}
	finalize := func(ctx environs.BootstrapContext, icfg *instancecfg.InstanceConfig) error {
		estate.ops <- OpFinalizeBootstrap{Context: ctx, Env: e.name, InstanceConfig: icfg}
		return nil
	}
	return arch, series, finalize, nil
}
Example #28
0
func (e *environ) Bootstrap(ctx environs.BootstrapContext, args environs.BootstrapParams) (arch, series string, _ environs.BootstrapFinalizer, _ error) {
	series = config.PreferredSeries(e.Config())
	availableTools, err := args.AvailableTools.Match(coretools.Filter{Series: series})
	if err != nil {
		return "", "", nil, err
	}
	arch = availableTools.Arches()[0]

	defer delay()
	if err := e.checkBroken("Bootstrap"); err != nil {
		return "", "", nil, err
	}
	network.InitializeFromConfig(e.Config())
	password := e.Config().AdminSecret()
	if password == "" {
		return "", "", nil, fmt.Errorf("admin-secret is required for bootstrap")
	}
	if _, ok := e.Config().CACert(); !ok {
		return "", "", nil, fmt.Errorf("no CA certificate in environment configuration")
	}

	logger.Infof("would pick tools from %s", availableTools)
	cfg, err := environs.BootstrapConfig(e.Config())
	if err != nil {
		return "", "", nil, fmt.Errorf("cannot make bootstrap config: %v", err)
	}

	estate, err := e.state()
	if err != nil {
		return "", "", nil, err
	}
	estate.mu.Lock()
	defer estate.mu.Unlock()
	if estate.bootstrapped {
		return "", "", nil, fmt.Errorf("environment is already bootstrapped")
	}
	estate.preferIPv6 = e.Config().PreferIPv6()

	// Create an instance for the bootstrap node.
	logger.Infof("creating bootstrap instance")
	i := &dummyInstance{
		id:           BootstrapInstanceId,
		addresses:    network.NewAddresses("localhost"),
		ports:        make(map[network.PortRange]bool),
		machineId:    agent.BootstrapMachineId,
		series:       series,
		firewallMode: e.Config().FirewallMode(),
		state:        estate,
		stateServer:  true,
	}
	estate.insts[i.id] = i

	if e.ecfg().stateServer() {
		// TODO(rog) factor out relevant code from cmd/jujud/bootstrap.go
		// so that we can call it here.

		info := stateInfo(estate.preferIPv6)
		st, err := state.Initialize(info, cfg, mongo.DefaultDialOpts(), estate.statePolicy)
		if err != nil {
			panic(err)
		}
		if err := st.SetEnvironConstraints(args.Constraints); err != nil {
			panic(err)
		}
		if err := st.SetAdminMongoPassword(password); err != nil {
			panic(err)
		}
		if err := st.MongoSession().DB("admin").Login("admin", password); err != nil {
			panic(err)
		}
		_, err = st.AddAdminUser(password)
		if err != nil {
			panic(err)
		}
		estate.apiServer, err = apiserver.NewServer(st, estate.apiListener, apiserver.ServerConfig{
			Cert:    []byte(testing.ServerCert),
			Key:     []byte(testing.ServerKey),
			DataDir: DataDir,
			LogDir:  LogDir,
		})
		if err != nil {
			panic(err)
		}
		estate.apiState = st
	}
	estate.bootstrapped = true
	estate.ops <- OpBootstrap{Context: ctx, Env: e.name, Args: args}
	finalize := func(ctx environs.BootstrapContext, mcfg *cloudinit.MachineConfig) error {
		estate.ops <- OpFinalizeBootstrap{Context: ctx, Env: e.name, MachineConfig: mcfg}
		return nil
	}
	return arch, series, finalize, nil
}
Example #29
0
// InitializeState should be called on the bootstrap machine's agent
// configuration. It uses that information to create the controller, dial the
// controller, and initialize it. It also generates a new password for the
// bootstrap machine and calls Write to save the the configuration.
//
// The cfg values will be stored in the state's ModelConfig; the
// machineCfg values will be used to configure the bootstrap Machine,
// and its constraints will be also be used for the model-level
// constraints. The connection to the controller will respect the
// given timeout parameter.
//
// InitializeState returns the newly initialized state and bootstrap
// machine. If it fails, the state may well be irredeemably compromised.
func InitializeState(
	adminUser names.UserTag,
	c agent.ConfigSetter,
	args InitializeStateParams,
	dialOpts mongo.DialOpts,
	newPolicy state.NewPolicyFunc,
) (_ *state.State, _ *state.Machine, resultErr error) {
	if c.Tag() != names.NewMachineTag(agent.BootstrapMachineId) {
		return nil, nil, errors.Errorf("InitializeState not called with bootstrap machine's configuration")
	}
	servingInfo, ok := c.StateServingInfo()
	if !ok {
		return nil, nil, errors.Errorf("state serving information not available")
	}
	// N.B. no users are set up when we're initializing the state,
	// so don't use any tag or password when opening it.
	info, ok := c.MongoInfo()
	if !ok {
		return nil, nil, errors.Errorf("stateinfo not available")
	}
	info.Tag = nil
	info.Password = c.OldPassword()

	if err := initMongoAdminUser(info.Info, dialOpts, info.Password); err != nil {
		return nil, nil, errors.Annotate(err, "failed to initialize mongo admin user")
	}

	cloudCredentials := make(map[names.CloudCredentialTag]cloud.Credential)
	var cloudCredentialTag names.CloudCredentialTag
	if args.ControllerCloudCredential != nil && args.ControllerCloudCredentialName != "" {
		cloudCredentialTag = names.NewCloudCredentialTag(fmt.Sprintf(
			"%s/%s/%s",
			args.ControllerCloudName,
			adminUser.Canonical(),
			args.ControllerCloudCredentialName,
		))
		cloudCredentials[cloudCredentialTag] = *args.ControllerCloudCredential
	}

	logger.Debugf("initializing address %v", info.Addrs)
	st, err := state.Initialize(state.InitializeParams{
		Clock: clock.WallClock,
		ControllerModelArgs: state.ModelArgs{
			Owner:                   adminUser,
			Config:                  args.ControllerModelConfig,
			Constraints:             args.ModelConstraints,
			CloudName:               args.ControllerCloudName,
			CloudRegion:             args.ControllerCloudRegion,
			CloudCredential:         cloudCredentialTag,
			StorageProviderRegistry: args.StorageProviderRegistry,
		},
		CloudName:                 args.ControllerCloudName,
		Cloud:                     args.ControllerCloud,
		CloudCredentials:          cloudCredentials,
		ControllerConfig:          args.ControllerConfig,
		ControllerInheritedConfig: args.ControllerInheritedConfig,
		RegionInheritedConfig:     args.RegionInheritedConfig,
		MongoInfo:                 info,
		MongoDialOpts:             dialOpts,
		NewPolicy:                 newPolicy,
	})
	if err != nil {
		return nil, nil, errors.Errorf("failed to initialize state: %v", err)
	}
	logger.Debugf("connected to initial state")
	defer func() {
		if resultErr != nil {
			st.Close()
		}
	}()
	servingInfo.SharedSecret = args.SharedSecret
	c.SetStateServingInfo(servingInfo)

	// Filter out any LXC or LXD bridge addresses from the machine addresses.
	args.BootstrapMachineAddresses = network.FilterBridgeAddresses(args.BootstrapMachineAddresses)

	if err = initAPIHostPorts(c, st, args.BootstrapMachineAddresses, servingInfo.APIPort); err != nil {
		return nil, nil, err
	}
	ssi := paramsStateServingInfoToStateStateServingInfo(servingInfo)
	if err := st.SetStateServingInfo(ssi); err != nil {
		return nil, nil, errors.Errorf("cannot set state serving info: %v", err)
	}
	m, err := initBootstrapMachine(c, st, args)
	if err != nil {
		return nil, nil, errors.Annotate(err, "cannot initialize bootstrap machine")
	}

	// Create the initial hosted model, with the model config passed to
	// bootstrap, which contains the UUID, name for the hosted model,
	// and any user supplied config. We also copy the authorized-keys
	// from the controller model.
	attrs := make(map[string]interface{})
	for k, v := range args.HostedModelConfig {
		attrs[k] = v
	}
	attrs[config.AuthorizedKeysKey] = args.ControllerModelConfig.AuthorizedKeys()

	// Construct a CloudSpec to pass on to NewModelConfig below.
	cloudSpec, err := environs.MakeCloudSpec(
		args.ControllerCloud,
		args.ControllerCloudName,
		args.ControllerCloudRegion,
		args.ControllerCloudCredential,
	)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	controllerUUID := args.ControllerConfig.ControllerUUID()
	creator := modelmanager.ModelConfigCreator{Provider: args.Provider}
	hostedModelConfig, err := creator.NewModelConfig(
		cloudSpec, args.ControllerModelConfig, attrs,
	)
	if err != nil {
		return nil, nil, errors.Annotate(err, "creating hosted model config")
	}
	provider, err := args.Provider(cloudSpec.Type)
	if err != nil {
		return nil, nil, errors.Annotate(err, "getting environ provider")
	}
	hostedModelEnv, err := provider.Open(environs.OpenParams{
		Cloud:  cloudSpec,
		Config: hostedModelConfig,
	})
	if err != nil {
		return nil, nil, errors.Annotate(err, "opening hosted model environment")
	}
	if err := hostedModelEnv.Create(environs.CreateParams{
		ControllerUUID: controllerUUID,
	}); err != nil {
		return nil, nil, errors.Annotate(err, "creating hosted model environment")
	}

	_, hostedModelState, err := st.NewModel(state.ModelArgs{
		Owner:                   adminUser,
		Config:                  hostedModelConfig,
		Constraints:             args.ModelConstraints,
		CloudName:               args.ControllerCloudName,
		CloudRegion:             args.ControllerCloudRegion,
		CloudCredential:         cloudCredentialTag,
		StorageProviderRegistry: args.StorageProviderRegistry,
	})
	if err != nil {
		return nil, nil, errors.Annotate(err, "creating hosted model")
	}
	hostedModelState.Close()

	return st, m, nil
}