github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/agent/agent_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Copyright 2014 Cloudbase Solutions SRL
     3  // Licensed under the AGPLv3, see LICENCE file for details.
     4  
     5  package agent_test
     6  
     7  import (
     8  	"fmt"
     9  	"path/filepath"
    10  	"reflect"
    11  
    12  	"github.com/juju/names"
    13  	jc "github.com/juju/testing/checkers"
    14  	gc "gopkg.in/check.v1"
    15  
    16  	"github.com/juju/juju/agent"
    17  	"github.com/juju/juju/api"
    18  	"github.com/juju/juju/apiserver/params"
    19  	"github.com/juju/juju/mongo"
    20  	"github.com/juju/juju/network"
    21  	"github.com/juju/juju/state/multiwatcher"
    22  	"github.com/juju/juju/testing"
    23  	"github.com/juju/juju/version"
    24  )
    25  
    26  type suite struct {
    27  	testing.BaseSuite
    28  }
    29  
    30  var _ = gc.Suite(&suite{})
    31  
    32  var agentConfigTests = []struct {
    33  	about         string
    34  	params        agent.AgentConfigParams
    35  	checkErr      string
    36  	inspectConfig func(*gc.C, agent.Config)
    37  }{{
    38  	about:    "missing data directory",
    39  	checkErr: "data directory not found in configuration",
    40  }, {
    41  	about: "missing tag",
    42  	params: agent.AgentConfigParams{
    43  		DataDir: "/data/dir",
    44  	},
    45  	checkErr: "entity tag not found in configuration",
    46  }, {
    47  	about: "missing upgraded to version",
    48  	params: agent.AgentConfigParams{
    49  		DataDir: "/data/dir",
    50  		Tag:     names.NewMachineTag("1"),
    51  	},
    52  	checkErr: "upgradedToVersion not found in configuration",
    53  }, {
    54  	about: "missing password",
    55  	params: agent.AgentConfigParams{
    56  		DataDir:           "/data/dir",
    57  		Tag:               names.NewMachineTag("1"),
    58  		UpgradedToVersion: version.Current.Number,
    59  	},
    60  	checkErr: "password not found in configuration",
    61  }, {
    62  	about: "missing environment tag",
    63  	params: agent.AgentConfigParams{
    64  		DataDir:           "/data/dir",
    65  		Tag:               names.NewMachineTag("1"),
    66  		UpgradedToVersion: version.Current.Number,
    67  		Password:          "sekrit",
    68  	},
    69  	checkErr: "environment not found in configuration",
    70  }, {
    71  	about: "invalid environment tag",
    72  	params: agent.AgentConfigParams{
    73  		DataDir:           "/data/dir",
    74  		Tag:               names.NewMachineTag("1"),
    75  		UpgradedToVersion: version.Current.Number,
    76  		Password:          "sekrit",
    77  		Environment:       names.NewEnvironTag("uuid"),
    78  	},
    79  	checkErr: `"uuid" is not a valid environment uuid`,
    80  }, {
    81  	about: "missing CA cert",
    82  	params: agent.AgentConfigParams{
    83  		DataDir:           "/data/dir",
    84  		Tag:               names.NewMachineTag("1"),
    85  		UpgradedToVersion: version.Current.Number,
    86  		Password:          "sekrit",
    87  		Environment:       testing.EnvironmentTag,
    88  	},
    89  	checkErr: "CA certificate not found in configuration",
    90  }, {
    91  	about: "need either state or api addresses",
    92  	params: agent.AgentConfigParams{
    93  		DataDir:           "/data/dir",
    94  		Tag:               names.NewMachineTag("1"),
    95  		UpgradedToVersion: version.Current.Number,
    96  		Password:          "sekrit",
    97  		CACert:            "ca cert",
    98  		Environment:       testing.EnvironmentTag,
    99  	},
   100  	checkErr: "state or API addresses not found in configuration",
   101  }, {
   102  	about: "invalid state address",
   103  	params: agent.AgentConfigParams{
   104  		DataDir:           "/data/dir",
   105  		Tag:               names.NewMachineTag("1"),
   106  		UpgradedToVersion: version.Current.Number,
   107  		Password:          "sekrit",
   108  		CACert:            "ca cert",
   109  		Environment:       testing.EnvironmentTag,
   110  		StateAddresses:    []string{"localhost:8080", "bad-address"},
   111  	},
   112  	checkErr: `invalid state server address "bad-address"`,
   113  }, {
   114  	about: "invalid api address",
   115  	params: agent.AgentConfigParams{
   116  		DataDir:           "/data/dir",
   117  		Tag:               names.NewMachineTag("1"),
   118  		UpgradedToVersion: version.Current.Number,
   119  		Password:          "sekrit",
   120  		CACert:            "ca cert",
   121  		Environment:       testing.EnvironmentTag,
   122  		APIAddresses:      []string{"localhost:8080", "bad-address"},
   123  	},
   124  	checkErr: `invalid API server address "bad-address"`,
   125  }, {
   126  	about: "good state addresses",
   127  	params: agent.AgentConfigParams{
   128  		DataDir:           "/data/dir",
   129  		Tag:               names.NewMachineTag("1"),
   130  		UpgradedToVersion: version.Current.Number,
   131  		Password:          "sekrit",
   132  		CACert:            "ca cert",
   133  		Environment:       testing.EnvironmentTag,
   134  		StateAddresses:    []string{"localhost:1234"},
   135  	},
   136  }, {
   137  	about: "good api addresses",
   138  	params: agent.AgentConfigParams{
   139  		DataDir:           "/data/dir",
   140  		Tag:               names.NewMachineTag("1"),
   141  		UpgradedToVersion: version.Current.Number,
   142  		Password:          "sekrit",
   143  		CACert:            "ca cert",
   144  		Environment:       testing.EnvironmentTag,
   145  		APIAddresses:      []string{"localhost:1234"},
   146  	},
   147  }, {
   148  	about: "both state and api addresses",
   149  	params: agent.AgentConfigParams{
   150  		DataDir:           "/data/dir",
   151  		Tag:               names.NewMachineTag("1"),
   152  		UpgradedToVersion: version.Current.Number,
   153  		Password:          "sekrit",
   154  		CACert:            "ca cert",
   155  		Environment:       testing.EnvironmentTag,
   156  		StateAddresses:    []string{"localhost:1234"},
   157  		APIAddresses:      []string{"localhost:1235"},
   158  	},
   159  }, {
   160  	about: "everything...",
   161  	params: agent.AgentConfigParams{
   162  		DataDir:           "/data/dir",
   163  		Tag:               names.NewMachineTag("1"),
   164  		Password:          "sekrit",
   165  		UpgradedToVersion: version.Current.Number,
   166  		CACert:            "ca cert",
   167  		Environment:       testing.EnvironmentTag,
   168  		StateAddresses:    []string{"localhost:1234"},
   169  		APIAddresses:      []string{"localhost:1235"},
   170  		Nonce:             "a nonce",
   171  	},
   172  }, {
   173  	about: "missing logDir sets default",
   174  	params: agent.AgentConfigParams{
   175  		DataDir:           "/data/dir",
   176  		Tag:               names.NewMachineTag("1"),
   177  		Password:          "sekrit",
   178  		UpgradedToVersion: version.Current.Number,
   179  		CACert:            "ca cert",
   180  		Environment:       testing.EnvironmentTag,
   181  		StateAddresses:    []string{"localhost:1234"},
   182  		APIAddresses:      []string{"localhost:1235"},
   183  		Nonce:             "a nonce",
   184  	},
   185  	inspectConfig: func(c *gc.C, cfg agent.Config) {
   186  		c.Check(cfg.LogDir(), gc.Equals, agent.DefaultLogDir)
   187  	},
   188  }, {
   189  	about: "agentConfig must not be a User tag",
   190  	params: agent.AgentConfigParams{
   191  		DataDir:           "/data/dir",
   192  		Tag:               names.NewUserTag("admin"), // this is a joke, the admin user is nil.
   193  		UpgradedToVersion: version.Current.Number,
   194  		Password:          "sekrit",
   195  	},
   196  	checkErr: "entity tag must be MachineTag or UnitTag, got names.UserTag",
   197  }, {
   198  	about: "agentConfig accepts a Unit tag",
   199  	params: agent.AgentConfigParams{
   200  		DataDir:           "/data/dir",
   201  		Tag:               names.NewUnitTag("ubuntu/1"),
   202  		Password:          "sekrit",
   203  		UpgradedToVersion: version.Current.Number,
   204  		Environment:       testing.EnvironmentTag,
   205  		CACert:            "ca cert",
   206  		StateAddresses:    []string{"localhost:1234"},
   207  		APIAddresses:      []string{"localhost:1235"},
   208  	},
   209  	inspectConfig: func(c *gc.C, cfg agent.Config) {
   210  		c.Check(cfg.Dir(), gc.Equals, "/data/dir/agents/unit-ubuntu-1")
   211  	},
   212  }, {
   213  	about: "prefer-ipv6 parsed when set",
   214  	params: agent.AgentConfigParams{
   215  		DataDir:           "/data/dir",
   216  		Tag:               names.NewMachineTag("1"),
   217  		Password:          "sekrit",
   218  		UpgradedToVersion: version.Current.Number,
   219  		CACert:            "ca cert",
   220  		Environment:       testing.EnvironmentTag,
   221  		StateAddresses:    []string{"localhost:1234"},
   222  		APIAddresses:      []string{"localhost:1235"},
   223  		Nonce:             "a nonce",
   224  		PreferIPv6:        true,
   225  	},
   226  	inspectConfig: func(c *gc.C, cfg agent.Config) {
   227  		c.Check(cfg.PreferIPv6(), jc.IsTrue)
   228  	},
   229  }, {
   230  	about: "missing prefer-ipv6 defaults to false",
   231  	params: agent.AgentConfigParams{
   232  		DataDir:           "/data/dir",
   233  		Tag:               names.NewMachineTag("1"),
   234  		Password:          "sekrit",
   235  		UpgradedToVersion: version.Current.Number,
   236  		CACert:            "ca cert",
   237  		Environment:       testing.EnvironmentTag,
   238  		StateAddresses:    []string{"localhost:1234"},
   239  		APIAddresses:      []string{"localhost:1235"},
   240  		Nonce:             "a nonce",
   241  	},
   242  	inspectConfig: func(c *gc.C, cfg agent.Config) {
   243  		c.Check(cfg.PreferIPv6(), jc.IsFalse)
   244  	},
   245  }}
   246  
   247  func (*suite) TestNewAgentConfig(c *gc.C) {
   248  	for i, test := range agentConfigTests {
   249  		c.Logf("%v: %s", i, test.about)
   250  		config, err := agent.NewAgentConfig(test.params)
   251  		if test.checkErr == "" {
   252  			c.Assert(err, jc.ErrorIsNil)
   253  			if test.inspectConfig != nil {
   254  				test.inspectConfig(c, config)
   255  			}
   256  		} else {
   257  			c.Assert(err, gc.ErrorMatches, test.checkErr)
   258  		}
   259  	}
   260  }
   261  
   262  func (*suite) TestMigrate(c *gc.C) {
   263  	initialParams := agent.AgentConfigParams{
   264  		DataDir:           c.MkDir(),
   265  		LogDir:            c.MkDir(),
   266  		Tag:               names.NewMachineTag("1"),
   267  		Nonce:             "nonce",
   268  		Password:          "secret",
   269  		UpgradedToVersion: version.MustParse("1.16.5"),
   270  		Jobs: []multiwatcher.MachineJob{
   271  			multiwatcher.JobManageEnviron,
   272  			multiwatcher.JobHostUnits,
   273  		},
   274  		CACert:         "ca cert",
   275  		Environment:    testing.EnvironmentTag,
   276  		StateAddresses: []string{"localhost:1234"},
   277  		APIAddresses:   []string{"localhost:4321"},
   278  		Values: map[string]string{
   279  			"key1": "value1",
   280  			"key2": "value2",
   281  			"key3": "value3",
   282  		},
   283  	}
   284  
   285  	migrateTests := []struct {
   286  		comment      string
   287  		fields       []string
   288  		newParams    agent.MigrateParams
   289  		expectValues map[string]string
   290  		expectErr    string
   291  	}{{
   292  		comment:   "nothing to change",
   293  		fields:    nil,
   294  		newParams: agent.MigrateParams{},
   295  	}, {
   296  		fields: []string{"DataDir"},
   297  		newParams: agent.MigrateParams{
   298  			DataDir: c.MkDir(),
   299  		},
   300  	}, {
   301  		fields: []string{"DataDir", "LogDir"},
   302  		newParams: agent.MigrateParams{
   303  			DataDir: c.MkDir(),
   304  			LogDir:  c.MkDir(),
   305  		},
   306  	}, {
   307  		fields: []string{"Jobs"},
   308  		newParams: agent.MigrateParams{
   309  			Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits},
   310  		},
   311  	}, {
   312  		comment:   "invalid/immutable field specified",
   313  		fields:    []string{"InvalidField"},
   314  		newParams: agent.MigrateParams{},
   315  		expectErr: `unknown field "InvalidField"`,
   316  	}, {
   317  		comment: "Values can be added, changed or removed",
   318  		fields:  []string{"Values", "DeleteValues"},
   319  		newParams: agent.MigrateParams{
   320  			DeleteValues: []string{"key2", "key3"}, // delete
   321  			Values: map[string]string{
   322  				"key1":     "new value1", // change
   323  				"new key3": "value3",     // add
   324  				"empty":    "",           // add empty val
   325  			},
   326  		},
   327  		expectValues: map[string]string{
   328  			"key1":     "new value1",
   329  			"new key3": "value3",
   330  			"empty":    "",
   331  		},
   332  	}}
   333  	for i, test := range migrateTests {
   334  		summary := "migrate fields"
   335  		if test.comment != "" {
   336  			summary += " (" + test.comment + ") "
   337  		}
   338  		c.Logf("test %d: %s %v", i, summary, test.fields)
   339  
   340  		initialConfig, err := agent.NewAgentConfig(initialParams)
   341  		c.Assert(err, jc.ErrorIsNil)
   342  
   343  		newConfig, err := agent.NewAgentConfig(initialParams)
   344  		c.Assert(err, jc.ErrorIsNil)
   345  
   346  		c.Assert(initialConfig.Write(), gc.IsNil)
   347  		c.Assert(agent.ConfigFileExists(initialConfig), jc.IsTrue)
   348  
   349  		err = newConfig.Migrate(test.newParams)
   350  		c.Assert(err, jc.ErrorIsNil)
   351  		err = newConfig.Write()
   352  		c.Assert(err, jc.ErrorIsNil)
   353  		c.Assert(agent.ConfigFileExists(newConfig), jc.IsTrue)
   354  
   355  		// Make sure we can read it back successfully and it
   356  		// matches what we wrote.
   357  		configPath := agent.ConfigPath(newConfig.DataDir(), newConfig.Tag())
   358  		readConfig, err := agent.ReadConfig(configPath)
   359  		c.Check(err, jc.ErrorIsNil)
   360  		c.Check(newConfig, jc.DeepEquals, readConfig)
   361  
   362  		// Make sure only the specified fields were changed and
   363  		// the rest matches.
   364  		for _, field := range test.fields {
   365  			switch field {
   366  			case "Values":
   367  				err = agent.PatchConfig(initialConfig, field, test.expectValues)
   368  				c.Check(err, jc.ErrorIsNil)
   369  			case "DeleteValues":
   370  				err = agent.PatchConfig(initialConfig, field, test.newParams.DeleteValues)
   371  				c.Check(err, jc.ErrorIsNil)
   372  			default:
   373  				value := reflect.ValueOf(test.newParams).FieldByName(field)
   374  				if value.IsValid() && test.expectErr == "" {
   375  					err = agent.PatchConfig(initialConfig, field, value.Interface())
   376  					c.Check(err, jc.ErrorIsNil)
   377  				} else {
   378  					err = agent.PatchConfig(initialConfig, field, value)
   379  					c.Check(err, gc.ErrorMatches, test.expectErr)
   380  				}
   381  			}
   382  		}
   383  		c.Check(newConfig, jc.DeepEquals, initialConfig)
   384  	}
   385  }
   386  
   387  func stateServingInfo() params.StateServingInfo {
   388  	return params.StateServingInfo{
   389  		Cert:           "cert",
   390  		PrivateKey:     "key",
   391  		CAPrivateKey:   "ca key",
   392  		StatePort:      69,
   393  		APIPort:        47,
   394  		SharedSecret:   "shared",
   395  		SystemIdentity: "identity",
   396  	}
   397  }
   398  
   399  func (*suite) TestNewStateMachineConfig(c *gc.C) {
   400  	type testStruct struct {
   401  		about         string
   402  		params        agent.AgentConfigParams
   403  		servingInfo   params.StateServingInfo
   404  		checkErr      string
   405  		inspectConfig func(*gc.C, agent.Config)
   406  	}
   407  	var tests = []testStruct{{
   408  		about:    "missing state server cert",
   409  		checkErr: "state server cert not found in configuration",
   410  	}, {
   411  		about: "missing state server key",
   412  		servingInfo: params.StateServingInfo{
   413  			Cert: "server cert",
   414  		},
   415  		checkErr: "state server key not found in configuration",
   416  	}, {
   417  		about: "missing ca cert key",
   418  		servingInfo: params.StateServingInfo{
   419  			Cert:       "server cert",
   420  			PrivateKey: "server key",
   421  		},
   422  		checkErr: "ca cert key not found in configuration",
   423  	}, {
   424  		about: "missing state port",
   425  		servingInfo: params.StateServingInfo{
   426  			Cert:         "server cert",
   427  			PrivateKey:   "server key",
   428  			CAPrivateKey: "ca key",
   429  		},
   430  		checkErr: "state port not found in configuration",
   431  	}, {
   432  		about: "params api port",
   433  		servingInfo: params.StateServingInfo{
   434  			Cert:         "server cert",
   435  			PrivateKey:   "server key",
   436  			CAPrivateKey: "ca key",
   437  			StatePort:    69,
   438  		},
   439  		checkErr: "api port not found in configuration",
   440  	}}
   441  	for _, test := range agentConfigTests {
   442  		tests = append(tests, testStruct{
   443  			about:       test.about,
   444  			params:      test.params,
   445  			servingInfo: stateServingInfo(),
   446  			checkErr:    test.checkErr,
   447  		})
   448  	}
   449  
   450  	for i, test := range tests {
   451  		c.Logf("%v: %s", i, test.about)
   452  		cfg, err := agent.NewStateMachineConfig(test.params, test.servingInfo)
   453  		if test.checkErr == "" {
   454  			c.Assert(err, jc.ErrorIsNil)
   455  			if test.inspectConfig != nil {
   456  				test.inspectConfig(c, cfg)
   457  			}
   458  		} else {
   459  			c.Assert(err, gc.ErrorMatches, test.checkErr)
   460  		}
   461  	}
   462  }
   463  
   464  var attributeParams = agent.AgentConfigParams{
   465  	DataDir:           "/data/dir",
   466  	Tag:               names.NewMachineTag("1"),
   467  	UpgradedToVersion: version.Current.Number,
   468  	Password:          "sekrit",
   469  	CACert:            "ca cert",
   470  	StateAddresses:    []string{"localhost:1234"},
   471  	APIAddresses:      []string{"localhost:1235"},
   472  	Nonce:             "a nonce",
   473  	Environment:       testing.EnvironmentTag,
   474  }
   475  
   476  func (*suite) TestAttributes(c *gc.C) {
   477  	conf, err := agent.NewAgentConfig(attributeParams)
   478  	c.Assert(err, jc.ErrorIsNil)
   479  	c.Assert(conf.DataDir(), gc.Equals, "/data/dir")
   480  	compareSystemIdentityPath := filepath.FromSlash("/data/dir/system-identity")
   481  	systemIdentityPath := filepath.FromSlash(conf.SystemIdentityPath())
   482  	c.Assert(systemIdentityPath, gc.Equals, compareSystemIdentityPath)
   483  	c.Assert(conf.Tag(), gc.Equals, names.NewMachineTag("1"))
   484  	c.Assert(conf.Dir(), gc.Equals, "/data/dir/agents/machine-1")
   485  	c.Assert(conf.Nonce(), gc.Equals, "a nonce")
   486  	c.Assert(conf.UpgradedToVersion(), jc.DeepEquals, version.Current.Number)
   487  }
   488  
   489  func (*suite) TestStateServingInfo(c *gc.C) {
   490  	servingInfo := stateServingInfo()
   491  	conf, err := agent.NewStateMachineConfig(attributeParams, servingInfo)
   492  	c.Assert(err, jc.ErrorIsNil)
   493  	gotInfo, ok := conf.StateServingInfo()
   494  	c.Assert(ok, jc.IsTrue)
   495  	c.Assert(gotInfo, jc.DeepEquals, servingInfo)
   496  	newInfo := params.StateServingInfo{
   497  		APIPort:        147,
   498  		StatePort:      169,
   499  		Cert:           "new cert",
   500  		PrivateKey:     "new key",
   501  		CAPrivateKey:   "new ca key",
   502  		SharedSecret:   "new shared",
   503  		SystemIdentity: "new identity",
   504  	}
   505  	conf.SetStateServingInfo(newInfo)
   506  	gotInfo, ok = conf.StateServingInfo()
   507  	c.Assert(ok, jc.IsTrue)
   508  	c.Assert(gotInfo, jc.DeepEquals, newInfo)
   509  }
   510  
   511  func (*suite) TestStateServingInfoNotAvailable(c *gc.C) {
   512  	conf, err := agent.NewAgentConfig(attributeParams)
   513  	c.Assert(err, jc.ErrorIsNil)
   514  
   515  	_, available := conf.StateServingInfo()
   516  	c.Assert(available, jc.IsFalse)
   517  }
   518  
   519  func (s *suite) TestAPIAddressesCannotWriteBack(c *gc.C) {
   520  	conf, err := agent.NewAgentConfig(attributeParams)
   521  	c.Assert(err, jc.ErrorIsNil)
   522  	value, err := conf.APIAddresses()
   523  	c.Assert(err, jc.ErrorIsNil)
   524  	c.Assert(value, jc.DeepEquals, []string{"localhost:1235"})
   525  	value[0] = "invalidAdr"
   526  	//Check out change hasn't gone back into the internals
   527  	newValue, err := conf.APIAddresses()
   528  	c.Assert(err, jc.ErrorIsNil)
   529  	c.Assert(newValue, jc.DeepEquals, []string{"localhost:1235"})
   530  }
   531  
   532  func (*suite) TestWriteAndRead(c *gc.C) {
   533  	testParams := attributeParams
   534  	testParams.DataDir = c.MkDir()
   535  	testParams.LogDir = c.MkDir()
   536  	conf, err := agent.NewAgentConfig(testParams)
   537  	c.Assert(err, jc.ErrorIsNil)
   538  
   539  	c.Assert(conf.Write(), gc.IsNil)
   540  	reread, err := agent.ReadConfig(agent.ConfigPath(conf.DataDir(), conf.Tag()))
   541  	c.Assert(err, jc.ErrorIsNil)
   542  	c.Assert(reread, jc.DeepEquals, conf)
   543  }
   544  
   545  func (*suite) TestAPIInfoAddsLocalhostWhenServingInfoPresent(c *gc.C) {
   546  	attrParams := attributeParams
   547  	servingInfo := stateServingInfo()
   548  	conf, err := agent.NewStateMachineConfig(attrParams, servingInfo)
   549  	c.Assert(err, jc.ErrorIsNil)
   550  	apiinfo := conf.APIInfo()
   551  	c.Check(apiinfo.Addrs, gc.HasLen, len(attrParams.APIAddresses)+1)
   552  	localhostAddressFound := false
   553  	for _, eachApiAddress := range apiinfo.Addrs {
   554  		if eachApiAddress == "localhost:47" {
   555  			localhostAddressFound = true
   556  			break
   557  		}
   558  	}
   559  	c.Assert(localhostAddressFound, jc.IsTrue)
   560  }
   561  
   562  func (*suite) TestAPIInfoAddsLocalhostWhenServingInfoPresentAndPreferIPv6On(c *gc.C) {
   563  	attrParams := attributeParams
   564  	attrParams.PreferIPv6 = true
   565  	servingInfo := stateServingInfo()
   566  	conf, err := agent.NewStateMachineConfig(attrParams, servingInfo)
   567  	c.Assert(err, jc.ErrorIsNil)
   568  	apiinfo := conf.APIInfo()
   569  	c.Check(apiinfo.Addrs, gc.HasLen, len(attrParams.APIAddresses)+1)
   570  	localhostAddressFound := false
   571  	for _, eachApiAddress := range apiinfo.Addrs {
   572  		if eachApiAddress == "[::1]:47" {
   573  			localhostAddressFound = true
   574  			break
   575  		}
   576  		c.Check(eachApiAddress, gc.Not(gc.Equals), "localhost:47")
   577  	}
   578  	c.Assert(localhostAddressFound, jc.IsTrue)
   579  }
   580  
   581  func (*suite) TestMongoInfoHonorsPreferIPv6(c *gc.C) {
   582  	attrParams := attributeParams
   583  	attrParams.PreferIPv6 = true
   584  	servingInfo := stateServingInfo()
   585  	conf, err := agent.NewStateMachineConfig(attrParams, servingInfo)
   586  	c.Assert(err, jc.ErrorIsNil)
   587  	mongoInfo, ok := conf.MongoInfo()
   588  	c.Assert(ok, jc.IsTrue)
   589  	c.Check(mongoInfo.Info.Addrs, jc.DeepEquals, []string{"[::1]:69"})
   590  
   591  	attrParams.PreferIPv6 = false
   592  	conf, err = agent.NewStateMachineConfig(attrParams, servingInfo)
   593  	c.Assert(err, jc.ErrorIsNil)
   594  	mongoInfo, ok = conf.MongoInfo()
   595  	c.Assert(ok, jc.IsTrue)
   596  	c.Check(mongoInfo.Info.Addrs, jc.DeepEquals, []string{"127.0.0.1:69"})
   597  }
   598  
   599  func (*suite) TestAPIInfoDoesntAddLocalhostWhenNoServingInfoPreferIPv6Off(c *gc.C) {
   600  	attrParams := attributeParams
   601  	attrParams.PreferIPv6 = false
   602  	conf, err := agent.NewAgentConfig(attrParams)
   603  	c.Assert(err, jc.ErrorIsNil)
   604  	apiinfo := conf.APIInfo()
   605  	c.Assert(apiinfo.Addrs, gc.DeepEquals, attrParams.APIAddresses)
   606  }
   607  
   608  func (*suite) TestAPIInfoDoesntAddLocalhostWhenNoServingInfoPreferIPv6On(c *gc.C) {
   609  	attrParams := attributeParams
   610  	attrParams.PreferIPv6 = true
   611  	conf, err := agent.NewAgentConfig(attrParams)
   612  	c.Assert(err, jc.ErrorIsNil)
   613  	apiinfo := conf.APIInfo()
   614  	c.Assert(apiinfo.Addrs, gc.DeepEquals, attrParams.APIAddresses)
   615  }
   616  
   617  func (*suite) TestSetPassword(c *gc.C) {
   618  	attrParams := attributeParams
   619  	servingInfo := stateServingInfo()
   620  	servingInfo.APIPort = 1235
   621  	conf, err := agent.NewStateMachineConfig(attrParams, servingInfo)
   622  	c.Assert(err, jc.ErrorIsNil)
   623  
   624  	expectAPIInfo := &api.Info{
   625  		Addrs:      attrParams.APIAddresses,
   626  		CACert:     attrParams.CACert,
   627  		Tag:        attrParams.Tag,
   628  		Password:   "",
   629  		Nonce:      attrParams.Nonce,
   630  		EnvironTag: attrParams.Environment,
   631  	}
   632  	c.Assert(conf.APIInfo(), jc.DeepEquals, expectAPIInfo)
   633  	addr := fmt.Sprintf("127.0.0.1:%d", servingInfo.StatePort)
   634  	expectStateInfo := &mongo.MongoInfo{
   635  		Info: mongo.Info{
   636  			Addrs:  []string{addr},
   637  			CACert: attrParams.CACert,
   638  		},
   639  		Tag:      attrParams.Tag,
   640  		Password: "",
   641  	}
   642  	info, ok := conf.MongoInfo()
   643  	c.Assert(ok, jc.IsTrue)
   644  	c.Assert(info, jc.DeepEquals, expectStateInfo)
   645  
   646  	conf.SetPassword("newpassword")
   647  
   648  	expectAPIInfo.Password = "newpassword"
   649  	expectStateInfo.Password = "newpassword"
   650  
   651  	c.Assert(conf.APIInfo(), jc.DeepEquals, expectAPIInfo)
   652  	info, ok = conf.MongoInfo()
   653  	c.Assert(ok, jc.IsTrue)
   654  	c.Assert(info, jc.DeepEquals, expectStateInfo)
   655  }
   656  
   657  func (*suite) TestSetOldPassword(c *gc.C) {
   658  	conf, err := agent.NewAgentConfig(attributeParams)
   659  	c.Assert(err, jc.ErrorIsNil)
   660  
   661  	c.Assert(conf.OldPassword(), gc.Equals, attributeParams.Password)
   662  	conf.SetOldPassword("newoldpassword")
   663  	c.Assert(conf.OldPassword(), gc.Equals, "newoldpassword")
   664  }
   665  
   666  func (*suite) TestSetUpgradedToVersion(c *gc.C) {
   667  	conf, err := agent.NewAgentConfig(attributeParams)
   668  	c.Assert(err, jc.ErrorIsNil)
   669  
   670  	c.Assert(conf.UpgradedToVersion(), gc.Equals, version.Current.Number)
   671  
   672  	expectVers := version.MustParse("3.4.5")
   673  	conf.SetUpgradedToVersion(expectVers)
   674  	c.Assert(conf.UpgradedToVersion(), gc.Equals, expectVers)
   675  }
   676  
   677  func (*suite) TestSetAPIHostPorts(c *gc.C) {
   678  	conf, err := agent.NewAgentConfig(attributeParams)
   679  	c.Assert(err, jc.ErrorIsNil)
   680  
   681  	addrs, err := conf.APIAddresses()
   682  	c.Assert(err, jc.ErrorIsNil)
   683  	c.Assert(addrs, gc.DeepEquals, attributeParams.APIAddresses)
   684  
   685  	// The first cloud-local address for each server is used,
   686  	// else if there are none then the first public- or unknown-
   687  	// scope address.
   688  	//
   689  	// If a server has only machine-local addresses, or none
   690  	// at all, then it will be excluded.
   691  	server1 := network.NewAddresses("0.1.2.3", "0.1.2.4", "zeroonetwothree")
   692  	server1[0].Scope = network.ScopeCloudLocal
   693  	server1[1].Scope = network.ScopeCloudLocal
   694  	server1[2].Scope = network.ScopePublic
   695  	server2 := network.NewAddresses("127.0.0.1")
   696  	server2[0].Scope = network.ScopeMachineLocal
   697  	server3 := network.NewAddresses("0.1.2.5", "zeroonetwofive")
   698  	server3[0].Scope = network.ScopeUnknown
   699  	server3[1].Scope = network.ScopeUnknown
   700  	conf.SetAPIHostPorts([][]network.HostPort{
   701  		network.AddressesWithPort(server1, 123),
   702  		network.AddressesWithPort(server2, 124),
   703  		network.AddressesWithPort(server3, 125),
   704  	})
   705  	addrs, err = conf.APIAddresses()
   706  	c.Assert(err, jc.ErrorIsNil)
   707  	c.Assert(addrs, gc.DeepEquals, []string{"0.1.2.3:123", "0.1.2.5:125"})
   708  }