github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/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  	"time"
    11  
    12  	"github.com/juju/errors"
    13  	"github.com/juju/names/v5"
    14  	jc "github.com/juju/testing/checkers"
    15  	"github.com/juju/version/v2"
    16  	gc "gopkg.in/check.v1"
    17  
    18  	"github.com/juju/juju/agent"
    19  	"github.com/juju/juju/api"
    20  	"github.com/juju/juju/controller"
    21  	"github.com/juju/juju/core/network"
    22  	"github.com/juju/juju/mongo"
    23  	"github.com/juju/juju/testing"
    24  	jujuversion "github.com/juju/juju/version"
    25  )
    26  
    27  type suite struct {
    28  	testing.BaseSuite
    29  }
    30  
    31  var _ = gc.Suite(&suite{})
    32  
    33  var agentConfigTests = []struct {
    34  	about         string
    35  	params        agent.AgentConfigParams
    36  	checkErr      string
    37  	inspectConfig func(*gc.C, agent.Config)
    38  }{{
    39  	about:    "missing data directory",
    40  	checkErr: "data directory not found in configuration",
    41  }, {
    42  	about: "missing tag",
    43  	params: agent.AgentConfigParams{
    44  		Paths: agent.Paths{DataDir: "/data/dir"},
    45  	},
    46  	checkErr: "entity tag not found in configuration",
    47  }, {
    48  	about: "missing upgraded to version",
    49  	params: agent.AgentConfigParams{
    50  		Paths: agent.Paths{DataDir: "/data/dir"},
    51  		Tag:   names.NewMachineTag("1"),
    52  	},
    53  	checkErr: "upgradedToVersion not found in configuration",
    54  }, {
    55  	about: "missing password",
    56  	params: agent.AgentConfigParams{
    57  		Paths:             agent.Paths{DataDir: "/data/dir"},
    58  		Tag:               names.NewMachineTag("1"),
    59  		UpgradedToVersion: jujuversion.Current,
    60  	},
    61  	checkErr: "password not found in configuration",
    62  }, {
    63  	about: "missing model tag",
    64  	params: agent.AgentConfigParams{
    65  		Paths:             agent.Paths{DataDir: "/data/dir"},
    66  		Tag:               names.NewMachineTag("1"),
    67  		UpgradedToVersion: jujuversion.Current,
    68  		Password:          "sekrit",
    69  		Controller:        testing.ControllerTag,
    70  	},
    71  	checkErr: "model not found in configuration",
    72  }, {
    73  	about: "invalid model tag",
    74  	params: agent.AgentConfigParams{
    75  		Paths:             agent.Paths{DataDir: "/data/dir"},
    76  		Tag:               names.NewMachineTag("1"),
    77  		UpgradedToVersion: jujuversion.Current,
    78  		Password:          "sekrit",
    79  		Controller:        testing.ControllerTag,
    80  		Model:             names.NewModelTag("uuid"),
    81  	},
    82  	checkErr: `"uuid" is not a valid model uuid`,
    83  }, {
    84  	about: "missing controller tag",
    85  	params: agent.AgentConfigParams{
    86  		Paths:             agent.Paths{DataDir: "/data/dir"},
    87  		Tag:               names.NewMachineTag("1"),
    88  		UpgradedToVersion: jujuversion.Current,
    89  		Password:          "sekrit",
    90  		Model:             testing.ModelTag,
    91  	},
    92  	checkErr: "controller not found in configuration",
    93  }, {
    94  	about: "invalid controller tag",
    95  	params: agent.AgentConfigParams{
    96  		Paths:             agent.Paths{DataDir: "/data/dir"},
    97  		Tag:               names.NewMachineTag("1"),
    98  		UpgradedToVersion: jujuversion.Current,
    99  		Password:          "sekrit",
   100  		Controller:        names.NewControllerTag("uuid"),
   101  		Model:             testing.ModelTag,
   102  	},
   103  	checkErr: `"uuid" is not a valid controller uuid`,
   104  }, {
   105  	about: "missing CA cert",
   106  	params: agent.AgentConfigParams{
   107  		Paths:             agent.Paths{DataDir: "/data/dir"},
   108  		Tag:               names.NewMachineTag("1"),
   109  		UpgradedToVersion: jujuversion.Current,
   110  		Password:          "sekrit",
   111  		Controller:        testing.ControllerTag,
   112  		Model:             testing.ModelTag,
   113  	},
   114  	checkErr: "CA certificate not found in configuration",
   115  }, {
   116  	about: "need api addresses",
   117  	params: agent.AgentConfigParams{
   118  		Paths:             agent.Paths{DataDir: "/data/dir"},
   119  		Tag:               names.NewMachineTag("1"),
   120  		UpgradedToVersion: jujuversion.Current,
   121  		Password:          "sekrit",
   122  		CACert:            "ca cert",
   123  		Controller:        testing.ControllerTag,
   124  		Model:             testing.ModelTag,
   125  	},
   126  	checkErr: "API addresses not found in configuration",
   127  }, {
   128  	about: "invalid api address",
   129  	params: agent.AgentConfigParams{
   130  		Paths:             agent.Paths{DataDir: "/data/dir"},
   131  		Tag:               names.NewMachineTag("1"),
   132  		UpgradedToVersion: jujuversion.Current,
   133  		Password:          "sekrit",
   134  		CACert:            "ca cert",
   135  		Controller:        testing.ControllerTag,
   136  		Model:             testing.ModelTag,
   137  		APIAddresses:      []string{"localhost:8080", "bad-address"},
   138  	},
   139  	checkErr: `invalid API server address "bad-address"`,
   140  }, {
   141  	about: "good api addresses",
   142  	params: agent.AgentConfigParams{
   143  		Paths:             agent.Paths{DataDir: "/data/dir"},
   144  		Tag:               names.NewMachineTag("1"),
   145  		UpgradedToVersion: jujuversion.Current,
   146  		Password:          "sekrit",
   147  		CACert:            "ca cert",
   148  		Controller:        testing.ControllerTag,
   149  		Model:             testing.ModelTag,
   150  		APIAddresses:      []string{"localhost:1234"},
   151  	},
   152  }, {
   153  	about: "good api addresses for controller agent",
   154  	params: agent.AgentConfigParams{
   155  		Paths:             agent.Paths{DataDir: "/data/dir"},
   156  		Tag:               names.NewControllerAgentTag("0"),
   157  		UpgradedToVersion: jujuversion.Current,
   158  		Password:          "sekrit",
   159  		CACert:            "ca cert",
   160  		Controller:        testing.ControllerTag,
   161  		Model:             testing.ModelTag,
   162  		APIAddresses:      []string{"localhost:1234"},
   163  	},
   164  }, {
   165  	about: "everything...",
   166  	params: agent.AgentConfigParams{
   167  		Paths:             agent.Paths{DataDir: "/data/dir"},
   168  		Tag:               names.NewMachineTag("1"),
   169  		Password:          "sekrit",
   170  		UpgradedToVersion: jujuversion.Current,
   171  		CACert:            "ca cert",
   172  		Controller:        testing.ControllerTag,
   173  		Model:             testing.ModelTag,
   174  		APIAddresses:      []string{"localhost:1235"},
   175  		Nonce:             "a nonce",
   176  	},
   177  }, {
   178  	about: "missing logDir sets default",
   179  	params: agent.AgentConfigParams{
   180  		Paths:             agent.Paths{DataDir: "/data/dir"},
   181  		Tag:               names.NewMachineTag("1"),
   182  		Password:          "sekrit",
   183  		UpgradedToVersion: jujuversion.Current,
   184  		CACert:            "ca cert",
   185  		Controller:        testing.ControllerTag,
   186  		Model:             testing.ModelTag,
   187  		APIAddresses:      []string{"localhost:1235"},
   188  		Nonce:             "a nonce",
   189  	},
   190  	inspectConfig: func(c *gc.C, cfg agent.Config) {
   191  		c.Check(cfg.LogDir(), gc.Equals, agent.DefaultPaths.LogDir)
   192  	},
   193  }, {
   194  	about: "missing metricsSpoolDir sets default",
   195  	params: agent.AgentConfigParams{
   196  		Paths:             agent.Paths{DataDir: "/data/dir"},
   197  		Tag:               names.NewMachineTag("1"),
   198  		Password:          "sekrit",
   199  		UpgradedToVersion: jujuversion.Current,
   200  		CACert:            "ca cert",
   201  		Controller:        testing.ControllerTag,
   202  		Model:             testing.ModelTag,
   203  		APIAddresses:      []string{"localhost:1235"},
   204  		Nonce:             "a nonce",
   205  	},
   206  	inspectConfig: func(c *gc.C, cfg agent.Config) {
   207  		c.Check(cfg.MetricsSpoolDir(), gc.Equals, agent.DefaultPaths.MetricsSpoolDir)
   208  	},
   209  }, {
   210  	about: "setting a custom metricsSpoolDir",
   211  	params: agent.AgentConfigParams{
   212  		Paths: agent.Paths{
   213  			DataDir:         "/data/dir",
   214  			MetricsSpoolDir: "/tmp/nowhere",
   215  		},
   216  		Tag:               names.NewMachineTag("1"),
   217  		Password:          "sekrit",
   218  		UpgradedToVersion: jujuversion.Current,
   219  		CACert:            "ca cert",
   220  		Controller:        testing.ControllerTag,
   221  		Model:             testing.ModelTag,
   222  		APIAddresses:      []string{"localhost:1235"},
   223  		Nonce:             "a nonce",
   224  	},
   225  	inspectConfig: func(c *gc.C, cfg agent.Config) {
   226  		c.Check(cfg.MetricsSpoolDir(), gc.Equals, "/tmp/nowhere")
   227  	},
   228  }, {
   229  	about: "agentConfig must not be a User tag",
   230  	params: agent.AgentConfigParams{
   231  		Paths:             agent.Paths{DataDir: "/data/dir"},
   232  		Tag:               names.NewUserTag("admin"), // this is a joke, the admin user is nil.
   233  		UpgradedToVersion: jujuversion.Current,
   234  		Password:          "sekrit",
   235  	},
   236  	checkErr: "entity tag must be MachineTag, UnitTag, ApplicationTag or ControllerAgentTag, got names.UserTag",
   237  }, {
   238  	about: "agentConfig accepts a Unit tag",
   239  	params: agent.AgentConfigParams{
   240  		Paths:             agent.Paths{DataDir: "/data/dir"},
   241  		Tag:               names.NewUnitTag("ubuntu/1"),
   242  		Password:          "sekrit",
   243  		UpgradedToVersion: jujuversion.Current,
   244  		Controller:        testing.ControllerTag,
   245  		Model:             testing.ModelTag,
   246  		CACert:            "ca cert",
   247  		APIAddresses:      []string{"localhost:1235"},
   248  	},
   249  	inspectConfig: func(c *gc.C, cfg agent.Config) {
   250  		c.Check(cfg.Dir(), gc.Equals, "/data/dir/agents/unit-ubuntu-1")
   251  	},
   252  }, {
   253  	about: "agentConfig accepts an Application tag",
   254  	params: agent.AgentConfigParams{
   255  		Paths:             agent.Paths{DataDir: "/data/dir"},
   256  		Tag:               names.NewApplicationTag("ubuntu"),
   257  		Password:          "sekrit",
   258  		UpgradedToVersion: jujuversion.Current,
   259  		Controller:        testing.ControllerTag,
   260  		Model:             testing.ModelTag,
   261  		CACert:            "ca cert",
   262  		APIAddresses:      []string{"localhost:1235"},
   263  	},
   264  	inspectConfig: func(c *gc.C, cfg agent.Config) {
   265  		c.Check(cfg.Dir(), gc.Equals, "/data/dir/agents/application-ubuntu")
   266  	},
   267  }, {
   268  	about: "agentConfig accepts an Model tag",
   269  	params: agent.AgentConfigParams{
   270  		Paths:             agent.Paths{DataDir: "/data/dir"},
   271  		Tag:               testing.ModelTag,
   272  		Password:          "sekrit",
   273  		UpgradedToVersion: jujuversion.Current,
   274  		Controller:        testing.ControllerTag,
   275  		Model:             testing.ModelTag,
   276  		CACert:            "ca cert",
   277  		APIAddresses:      []string{"localhost:1235"},
   278  	},
   279  	inspectConfig: func(c *gc.C, cfg agent.Config) {
   280  		c.Check(cfg.Dir(), gc.Equals, "/data/dir/agents/model-deadbeef-0bad-400d-8000-4b1d0d06f00d")
   281  	},
   282  }}
   283  
   284  func (*suite) TestNewAgentConfig(c *gc.C) {
   285  	for i, test := range agentConfigTests {
   286  		c.Logf("%v: %s", i, test.about)
   287  		config, err := agent.NewAgentConfig(test.params)
   288  		if test.checkErr == "" {
   289  			c.Assert(err, jc.ErrorIsNil)
   290  			if test.inspectConfig != nil {
   291  				test.inspectConfig(c, config)
   292  			}
   293  		} else {
   294  			c.Assert(err, gc.ErrorMatches, test.checkErr)
   295  		}
   296  	}
   297  }
   298  
   299  func stateServingInfo() controller.StateServingInfo {
   300  	return controller.StateServingInfo{
   301  		Cert:              "cert",
   302  		PrivateKey:        "key",
   303  		CAPrivateKey:      "ca key",
   304  		StatePort:         69,
   305  		APIPort:           47,
   306  		ControllerAPIPort: 52,
   307  		SharedSecret:      "shared",
   308  		SystemIdentity:    "identity",
   309  	}
   310  }
   311  
   312  func (*suite) TestNewStateMachineConfig(c *gc.C) {
   313  	type testStruct struct {
   314  		about         string
   315  		params        agent.AgentConfigParams
   316  		servingInfo   controller.StateServingInfo
   317  		checkErr      string
   318  		inspectConfig func(*gc.C, agent.Config)
   319  	}
   320  	var tests = []testStruct{{
   321  		about:    "missing controller cert",
   322  		checkErr: "controller cert not found in configuration",
   323  	}, {
   324  		about: "missing controller key",
   325  		servingInfo: controller.StateServingInfo{
   326  			Cert: "server cert",
   327  		},
   328  		checkErr: "controller key not found in configuration",
   329  	}, {
   330  		about: "missing ca cert key",
   331  		servingInfo: controller.StateServingInfo{
   332  			Cert:       "server cert",
   333  			PrivateKey: "server key",
   334  		},
   335  		checkErr: "ca cert key not found in configuration",
   336  	}, {
   337  		about: "missing state port",
   338  		servingInfo: controller.StateServingInfo{
   339  			Cert:         "server cert",
   340  			PrivateKey:   "server key",
   341  			CAPrivateKey: "ca key",
   342  		},
   343  		checkErr: "state port not found in configuration",
   344  	}, {
   345  		about: "params api port",
   346  		servingInfo: controller.StateServingInfo{
   347  			Cert:         "server cert",
   348  			PrivateKey:   "server key",
   349  			CAPrivateKey: "ca key",
   350  			StatePort:    69,
   351  		},
   352  		checkErr: "api port not found in configuration",
   353  	}}
   354  	for _, test := range agentConfigTests {
   355  		tests = append(tests, testStruct{
   356  			about:       test.about,
   357  			params:      test.params,
   358  			servingInfo: stateServingInfo(),
   359  			checkErr:    test.checkErr,
   360  		})
   361  	}
   362  
   363  	for i, test := range tests {
   364  		c.Logf("%v: %s", i, test.about)
   365  		cfg, err := agent.NewStateMachineConfig(test.params, test.servingInfo)
   366  		if test.checkErr == "" {
   367  			c.Assert(err, jc.ErrorIsNil)
   368  			if test.inspectConfig != nil {
   369  				test.inspectConfig(c, cfg)
   370  			}
   371  		} else {
   372  			c.Assert(err, gc.ErrorMatches, test.checkErr)
   373  		}
   374  	}
   375  }
   376  
   377  var attributeParams = agent.AgentConfigParams{
   378  	Paths: agent.Paths{
   379  		DataDir: "/data/dir",
   380  	},
   381  	Tag:                    names.NewMachineTag("1"),
   382  	UpgradedToVersion:      jujuversion.Current,
   383  	Password:               "sekrit",
   384  	CACert:                 "ca cert",
   385  	APIAddresses:           []string{"localhost:1235"},
   386  	Nonce:                  "a nonce",
   387  	Controller:             testing.ControllerTag,
   388  	Model:                  testing.ModelTag,
   389  	JujuDBSnapChannel:      controller.DefaultJujuDBSnapChannel,
   390  	AgentLogfileMaxSizeMB:  150,
   391  	AgentLogfileMaxBackups: 4,
   392  }
   393  
   394  func (*suite) TestAttributes(c *gc.C) {
   395  	conf, err := agent.NewAgentConfig(attributeParams)
   396  	c.Assert(err, jc.ErrorIsNil)
   397  	c.Assert(conf.DataDir(), gc.Equals, "/data/dir")
   398  	compareSystemIdentityPath := filepath.FromSlash("/data/dir/system-identity")
   399  	systemIdentityPath := filepath.FromSlash(conf.SystemIdentityPath())
   400  	c.Assert(systemIdentityPath, gc.Equals, compareSystemIdentityPath)
   401  	c.Assert(conf.Tag(), gc.Equals, names.NewMachineTag("1"))
   402  	c.Assert(conf.Dir(), gc.Equals, "/data/dir/agents/machine-1")
   403  	c.Assert(conf.Nonce(), gc.Equals, "a nonce")
   404  	c.Assert(conf.UpgradedToVersion(), jc.DeepEquals, jujuversion.Current)
   405  	c.Assert(conf.JujuDBSnapChannel(), gc.Equals, "4.4/stable")
   406  	c.Assert(conf.AgentLogfileMaxSizeMB(), gc.Equals, 150)
   407  	c.Assert(conf.AgentLogfileMaxBackups(), gc.Equals, 4)
   408  }
   409  
   410  func (*suite) TestStateServingInfo(c *gc.C) {
   411  	servingInfo := stateServingInfo()
   412  	conf, err := agent.NewStateMachineConfig(attributeParams, servingInfo)
   413  	c.Assert(err, jc.ErrorIsNil)
   414  	gotInfo, ok := conf.StateServingInfo()
   415  	c.Assert(ok, jc.IsTrue)
   416  	c.Assert(gotInfo, jc.DeepEquals, servingInfo)
   417  	newInfo := controller.StateServingInfo{
   418  		APIPort:           147,
   419  		ControllerAPIPort: 148,
   420  		StatePort:         169,
   421  		Cert:              "new cert",
   422  		PrivateKey:        "new key",
   423  		CAPrivateKey:      "new ca key",
   424  		SharedSecret:      "new shared",
   425  		SystemIdentity:    "new identity",
   426  	}
   427  	conf.SetStateServingInfo(newInfo)
   428  	gotInfo, ok = conf.StateServingInfo()
   429  	c.Assert(ok, jc.IsTrue)
   430  	c.Assert(gotInfo, jc.DeepEquals, newInfo)
   431  }
   432  
   433  func (*suite) TestStateServingInfoNotAvailable(c *gc.C) {
   434  	conf, err := agent.NewAgentConfig(attributeParams)
   435  	c.Assert(err, jc.ErrorIsNil)
   436  
   437  	_, available := conf.StateServingInfo()
   438  	c.Assert(available, jc.IsFalse)
   439  }
   440  
   441  func (s *suite) TestAPIAddressesCannotWriteBack(c *gc.C) {
   442  	conf, err := agent.NewAgentConfig(attributeParams)
   443  	c.Assert(err, jc.ErrorIsNil)
   444  	value, err := conf.APIAddresses()
   445  	c.Assert(err, jc.ErrorIsNil)
   446  	c.Assert(value, jc.DeepEquals, []string{"localhost:1235"})
   447  	value[0] = "invalidAdr"
   448  	//Check out change hasn't gone back into the internals
   449  	newValue, err := conf.APIAddresses()
   450  	c.Assert(err, jc.ErrorIsNil)
   451  	c.Assert(newValue, jc.DeepEquals, []string{"localhost:1235"})
   452  }
   453  
   454  func (*suite) TestWriteAndRead(c *gc.C) {
   455  	testParams := attributeParams
   456  	testParams.Paths.DataDir = c.MkDir()
   457  	testParams.Paths.LogDir = c.MkDir()
   458  	conf, err := agent.NewAgentConfig(testParams)
   459  	c.Assert(err, jc.ErrorIsNil)
   460  
   461  	c.Assert(conf.Write(), gc.IsNil)
   462  	reread, err := agent.ReadConfig(agent.ConfigPath(conf.DataDir(), conf.Tag()))
   463  	c.Assert(err, jc.ErrorIsNil)
   464  	c.Assert(reread, jc.DeepEquals, conf)
   465  }
   466  
   467  func (*suite) TestParseConfigData(c *gc.C) {
   468  	testParams := attributeParams
   469  	testParams.Paths.DataDir = c.MkDir()
   470  	testParams.Paths.LogDir = c.MkDir()
   471  	conf, err := agent.NewAgentConfig(testParams)
   472  	c.Assert(err, jc.ErrorIsNil)
   473  	data, err := conf.Render()
   474  	c.Assert(err, jc.ErrorIsNil)
   475  	reread, err := agent.ParseConfigData(data)
   476  	c.Assert(err, jc.ErrorIsNil)
   477  	c.Assert(reread, jc.DeepEquals, conf)
   478  }
   479  
   480  func (*suite) TestAPIInfoMissingAddress(c *gc.C) {
   481  	conf := agent.EmptyConfig()
   482  	_, ok := conf.APIInfo()
   483  	c.Assert(ok, jc.IsFalse)
   484  }
   485  
   486  func (*suite) TestAPIInfoServesLocalhostWhenServingInfoPresent(c *gc.C) {
   487  	attrParams := attributeParams
   488  	attrParams.APIAddresses = []string{"foo.example:1235"}
   489  	servingInfo := stateServingInfo()
   490  	conf, err := agent.NewStateMachineConfig(attrParams, servingInfo)
   491  	c.Assert(err, jc.ErrorIsNil)
   492  	apiinfo, ok := conf.APIInfo()
   493  	c.Assert(ok, jc.IsTrue)
   494  	c.Check(apiinfo.Addrs, jc.SameContents, []string{"localhost:52", "foo.example:1235"})
   495  }
   496  
   497  func (*suite) TestAPIInfoServesStandardAPIPortWhenControllerAPIPortNotSet(c *gc.C) {
   498  	attrParams := attributeParams
   499  	attrParams.APIAddresses = []string{"foo.example:1235"}
   500  	servingInfo := stateServingInfo()
   501  	servingInfo.ControllerAPIPort = 0
   502  	conf, err := agent.NewStateMachineConfig(attrParams, servingInfo)
   503  	c.Assert(err, jc.ErrorIsNil)
   504  	apiinfo, ok := conf.APIInfo()
   505  	c.Assert(ok, jc.IsTrue)
   506  	c.Check(apiinfo.Addrs, jc.SameContents, []string{"localhost:47", "foo.example:1235"})
   507  }
   508  
   509  func (*suite) TestMongoInfo(c *gc.C) {
   510  	attrParams := attributeParams
   511  	attrParams.APIAddresses = []string{"foo.example:1235", "bar.example:1236", "localhost:88", "3.4.2.1:1070"}
   512  	servingInfo := stateServingInfo()
   513  	conf, err := agent.NewStateMachineConfig(attrParams, servingInfo)
   514  	c.Assert(err, jc.ErrorIsNil)
   515  	mongoInfo, ok := conf.MongoInfo()
   516  	c.Assert(ok, jc.IsTrue)
   517  	c.Check(mongoInfo.Info.Addrs, jc.DeepEquals, []string{"localhost:69", "3.4.2.1:69"})
   518  	c.Check(mongoInfo.Info.DisableTLS, jc.IsFalse)
   519  }
   520  
   521  func (*suite) TestMongoInfoNoCloudLocalAvailable(c *gc.C) {
   522  	attrParams := attributeParams
   523  	attrParams.APIAddresses = []string{"foo.example:1235", "bar.example:1236", "localhost:88"}
   524  	servingInfo := stateServingInfo()
   525  	conf, err := agent.NewStateMachineConfig(attrParams, servingInfo)
   526  	c.Assert(err, jc.ErrorIsNil)
   527  	mongoInfo, ok := conf.MongoInfo()
   528  	c.Assert(ok, jc.IsTrue)
   529  	c.Check(mongoInfo.Info.Addrs, jc.DeepEquals, []string{"localhost:69", "foo.example:69", "bar.example:69"})
   530  	c.Check(mongoInfo.Info.DisableTLS, jc.IsFalse)
   531  }
   532  
   533  func (*suite) TestPromotedMongoInfo(c *gc.C) {
   534  	attrParams := attributeParams
   535  	attrParams.APIAddresses = []string{"foo.example:1235", "bar.example:1236", "localhost:88", "3.4.2.1:1070"}
   536  	conf, err := agent.NewAgentConfig(attrParams)
   537  	c.Assert(err, jc.ErrorIsNil)
   538  
   539  	_, ok := conf.MongoInfo()
   540  	c.Assert(ok, jc.IsFalse)
   541  
   542  	// Promote the agent to a controller by
   543  	// setting state serving info. As soon
   544  	// as this is done, we should be able
   545  	// to use MongoInfo.
   546  	conf.SetStateServingInfo(stateServingInfo())
   547  
   548  	mongoInfo, ok := conf.MongoInfo()
   549  	c.Assert(ok, jc.IsTrue)
   550  	c.Check(mongoInfo.Info.Addrs, jc.DeepEquals, []string{"localhost:69", "3.4.2.1:69"})
   551  	c.Check(mongoInfo.Info.DisableTLS, jc.IsFalse)
   552  }
   553  
   554  func (*suite) TestAPIInfoDoesNotAddLocalhostWhenNoServingInfo(c *gc.C) {
   555  	attrParams := attributeParams
   556  	conf, err := agent.NewAgentConfig(attrParams)
   557  	c.Assert(err, jc.ErrorIsNil)
   558  	apiinfo, ok := conf.APIInfo()
   559  	c.Assert(ok, jc.IsTrue)
   560  	c.Assert(apiinfo.Addrs, gc.DeepEquals, attrParams.APIAddresses)
   561  }
   562  
   563  func (*suite) TestSetPassword(c *gc.C) {
   564  	attrParams := attributeParams
   565  	servingInfo := stateServingInfo()
   566  	servingInfo.ControllerAPIPort = 1235
   567  	conf, err := agent.NewStateMachineConfig(attrParams, servingInfo)
   568  	c.Assert(err, jc.ErrorIsNil)
   569  
   570  	expectAPIInfo := &api.Info{
   571  		Addrs:    attrParams.APIAddresses,
   572  		CACert:   attrParams.CACert,
   573  		Tag:      attrParams.Tag,
   574  		Password: "",
   575  		Nonce:    attrParams.Nonce,
   576  		ModelTag: attrParams.Model,
   577  	}
   578  	apiInfo, ok := conf.APIInfo()
   579  	c.Assert(ok, jc.IsTrue)
   580  	c.Assert(apiInfo, jc.DeepEquals, expectAPIInfo)
   581  	addr := fmt.Sprintf("localhost:%d", servingInfo.StatePort)
   582  	expectStateInfo := &mongo.MongoInfo{
   583  		Info: mongo.Info{
   584  			Addrs:  []string{addr},
   585  			CACert: attrParams.CACert,
   586  		},
   587  		Tag:      attrParams.Tag,
   588  		Password: "",
   589  	}
   590  	info, ok := conf.MongoInfo()
   591  	c.Assert(ok, jc.IsTrue)
   592  	c.Assert(info, jc.DeepEquals, expectStateInfo)
   593  
   594  	conf.SetPassword("newpassword")
   595  
   596  	expectAPIInfo.Password = "newpassword"
   597  	expectStateInfo.Password = "newpassword"
   598  
   599  	apiInfo, ok = conf.APIInfo()
   600  	c.Assert(ok, jc.IsTrue)
   601  	c.Assert(apiInfo, jc.DeepEquals, expectAPIInfo)
   602  	info, ok = conf.MongoInfo()
   603  	c.Assert(ok, jc.IsTrue)
   604  	c.Assert(info, jc.DeepEquals, expectStateInfo)
   605  }
   606  
   607  func (*suite) TestSetOldPassword(c *gc.C) {
   608  	conf, err := agent.NewAgentConfig(attributeParams)
   609  	c.Assert(err, jc.ErrorIsNil)
   610  
   611  	c.Assert(conf.OldPassword(), gc.Equals, attributeParams.Password)
   612  	conf.SetOldPassword("newoldpassword")
   613  	c.Assert(conf.OldPassword(), gc.Equals, "newoldpassword")
   614  }
   615  
   616  func (*suite) TestSetUpgradedToVersion(c *gc.C) {
   617  	conf, err := agent.NewAgentConfig(attributeParams)
   618  	c.Assert(err, jc.ErrorIsNil)
   619  
   620  	c.Assert(conf.UpgradedToVersion(), gc.Equals, jujuversion.Current)
   621  
   622  	expectVers := version.MustParse("3.4.5")
   623  	conf.SetUpgradedToVersion(expectVers)
   624  	c.Assert(conf.UpgradedToVersion(), gc.Equals, expectVers)
   625  }
   626  
   627  func (*suite) TestSetAPIHostPorts(c *gc.C) {
   628  	conf, err := agent.NewAgentConfig(attributeParams)
   629  	c.Assert(err, jc.ErrorIsNil)
   630  
   631  	addrs, err := conf.APIAddresses()
   632  	c.Assert(err, jc.ErrorIsNil)
   633  	c.Assert(addrs, gc.DeepEquals, attributeParams.APIAddresses)
   634  
   635  	// All the best candidate addresses for each server are
   636  	// used. Cloud-local addresses are preferred.  Otherwise, public
   637  	// or unknown scope addresses are used.
   638  	//
   639  	// If a server has only machine-local addresses, or none
   640  	// at all, then it will be excluded.
   641  	server1 := network.NewSpaceAddresses("0.1.0.1", "0.1.0.2", "host.com")
   642  	server1[0].Scope = network.ScopeCloudLocal
   643  	server1[1].Scope = network.ScopeCloudLocal
   644  	server1[2].Scope = network.ScopePublic
   645  
   646  	server2 := network.NewSpaceAddresses("0.2.0.1", "0.2.0.2")
   647  	server2[0].Scope = network.ScopePublic
   648  	server2[1].Scope = network.ScopePublic
   649  
   650  	server3 := network.NewSpaceAddresses("127.0.0.1")
   651  	server3[0].Scope = network.ScopeMachineLocal
   652  
   653  	server4 := network.NewSpaceAddresses("0.4.0.1", "elsewhere.net")
   654  	server4[0].Scope = network.ScopeUnknown
   655  	server4[1].Scope = network.ScopeUnknown
   656  
   657  	conf.SetAPIHostPorts([]network.HostPorts{
   658  		network.SpaceAddressesWithPort(server1, 1111).HostPorts(),
   659  		network.SpaceAddressesWithPort(server2, 2222).HostPorts(),
   660  		network.SpaceAddressesWithPort(server3, 3333).HostPorts(),
   661  		network.SpaceAddressesWithPort(server4, 4444).HostPorts(),
   662  	})
   663  	addrs, err = conf.APIAddresses()
   664  	c.Assert(err, jc.ErrorIsNil)
   665  	c.Assert(addrs, gc.DeepEquals, []string{
   666  		"0.1.0.1:1111",
   667  		"0.1.0.2:1111",
   668  		"host.com:1111",
   669  		"0.2.0.1:2222",
   670  		"0.2.0.2:2222",
   671  		"0.4.0.1:4444",
   672  		"elsewhere.net:4444",
   673  	})
   674  }
   675  
   676  func (*suite) TestSetAPIHostPortsErrorOnEmpty(c *gc.C) {
   677  	conf, err := agent.NewAgentConfig(attributeParams)
   678  	c.Assert(err, jc.ErrorIsNil)
   679  
   680  	err = conf.SetAPIHostPorts([]network.HostPorts{})
   681  	c.Assert(err, jc.Satisfies, errors.IsBadRequest)
   682  }
   683  
   684  func (*suite) TestSetCACert(c *gc.C) {
   685  	conf, err := agent.NewAgentConfig(attributeParams)
   686  	c.Assert(err, jc.ErrorIsNil)
   687  	c.Assert(conf.CACert(), gc.Equals, "ca cert")
   688  
   689  	conf.SetCACert("new ca cert")
   690  	c.Assert(conf.CACert(), gc.Equals, "new ca cert")
   691  }
   692  
   693  func (*suite) TestSetJujuDBSnapChannel(c *gc.C) {
   694  	conf, err := agent.NewAgentConfig(attributeParams)
   695  	c.Assert(err, jc.ErrorIsNil)
   696  
   697  	snapChannel := conf.JujuDBSnapChannel()
   698  	c.Assert(snapChannel, gc.Equals, attributeParams.JujuDBSnapChannel)
   699  
   700  	conf.SetJujuDBSnapChannel("latest/candidate")
   701  	snapChannel = conf.JujuDBSnapChannel()
   702  	c.Assert(snapChannel, gc.Equals, "latest/candidate", gc.Commentf("juju db snap channel setting not updated"))
   703  }
   704  
   705  func (*suite) TestSetQueryTracingEnabled(c *gc.C) {
   706  	conf, err := agent.NewAgentConfig(attributeParams)
   707  	c.Assert(err, jc.ErrorIsNil)
   708  
   709  	queryTracingEnabled := conf.QueryTracingEnabled()
   710  	c.Assert(queryTracingEnabled, gc.Equals, attributeParams.QueryTracingEnabled)
   711  
   712  	conf.SetQueryTracingEnabled(true)
   713  	queryTracingEnabled = conf.QueryTracingEnabled()
   714  	c.Assert(queryTracingEnabled, gc.Equals, true, gc.Commentf("query tracing enabled setting not updated"))
   715  }
   716  
   717  func (*suite) TestSetQueryTracingThreshold(c *gc.C) {
   718  	conf, err := agent.NewAgentConfig(attributeParams)
   719  	c.Assert(err, jc.ErrorIsNil)
   720  
   721  	queryTracingThreshold := conf.QueryTracingThreshold()
   722  	c.Assert(queryTracingThreshold, gc.Equals, attributeParams.QueryTracingThreshold)
   723  
   724  	conf.SetQueryTracingThreshold(time.Second * 10)
   725  	queryTracingThreshold = conf.QueryTracingThreshold()
   726  	c.Assert(queryTracingThreshold, gc.Equals, time.Second*10, gc.Commentf("query tracing threshold setting not updated"))
   727  }