From 12bf7b35c38d04ba53d417ed04ca1481f620b2f7 Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Tue, 30 Apr 2024 14:19:10 +0100 Subject: [PATCH 01/16] Assign `info.Tag` with username when no client credentials provided Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/api/connector/simpleconnector.go b/api/connector/simpleconnector.go index 7d459229432..0502d43fcef 100644 --- a/api/connector/simpleconnector.go +++ b/api/connector/simpleconnector.go @@ -52,16 +52,26 @@ func NewSimple(opts SimpleConfig, dialOptions ...api.DialOption) (*SimpleConnect CACert: opts.CACert, ModelTag: names.NewModelTag(opts.ModelUUID), - Tag: names.NewUserTag(opts.Username), Password: opts.Password, Macaroons: opts.Macaroons, } + + isClientCredentialsProvided := opts.ClientID != "" && opts.ClientSecret != "" + + // When the client intends to login via client credentials (like a service + // account) they leave `SimpleConfig.Username` empty and assign the client + // credentials to `SimpleConfig.ClientID` and `SimpleConfig.ClientSecret`. + // In such cases, assigning a user tag to `info.Tag` will result in panic. + if !isClientCredentialsProvided { + info.Tag = names.NewUserTag(opts.Username) + } + if err := info.Validate(); err != nil { return nil, err } dialOpts := api.DefaultDialOpts() - if opts.ClientID != "" && opts.ClientSecret != "" { + if isClientCredentialsProvided { dialOpts.LoginProvider = api.NewClientCredentialsLoginProvider( opts.ClientID, opts.ClientSecret, From 6462326fd0619b440fe55fc24bc534efd66f0a0a Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Tue, 30 Apr 2024 22:31:09 +0100 Subject: [PATCH 02/16] Leave password/macaroons empty when client creds provided Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/api/connector/simpleconnector.go b/api/connector/simpleconnector.go index 0502d43fcef..21ef0874c5a 100644 --- a/api/connector/simpleconnector.go +++ b/api/connector/simpleconnector.go @@ -51,9 +51,6 @@ func NewSimple(opts SimpleConfig, dialOptions ...api.DialOption) (*SimpleConnect Addrs: opts.ControllerAddresses, CACert: opts.CACert, ModelTag: names.NewModelTag(opts.ModelUUID), - - Password: opts.Password, - Macaroons: opts.Macaroons, } isClientCredentialsProvided := opts.ClientID != "" && opts.ClientSecret != "" @@ -64,6 +61,8 @@ func NewSimple(opts SimpleConfig, dialOptions ...api.DialOption) (*SimpleConnect // In such cases, assigning a user tag to `info.Tag` will result in panic. if !isClientCredentialsProvided { info.Tag = names.NewUserTag(opts.Username) + info.Password = opts.Password + info.Macaroons = opts.Macaroons } if err := info.Validate(); err != nil { From 1513d95a67ceff85687f8453665067efa048c97c Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Tue, 30 Apr 2024 22:31:41 +0100 Subject: [PATCH 03/16] Add tests to verify `NewSimple` handling client credentials Signed-off-by: Babak K. Shandiz --- api/connector/package_test.go | 14 ++++ api/connector/simpleconnector_test.go | 101 ++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 api/connector/package_test.go create mode 100644 api/connector/simpleconnector_test.go diff --git a/api/connector/package_test.go b/api/connector/package_test.go new file mode 100644 index 00000000000..fb3dddfeef1 --- /dev/null +++ b/api/connector/package_test.go @@ -0,0 +1,14 @@ +// Copyright 2020 Canonical Ltd. +// Licensed under the AGPLv3, see LICENCE file for details. + +package connector + +import ( + "testing" + + gc "gopkg.in/check.v1" +) + +func Test(t *testing.T) { + gc.TestingT(t) +} diff --git a/api/connector/simpleconnector_test.go b/api/connector/simpleconnector_test.go new file mode 100644 index 00000000000..05e9fb0dfb4 --- /dev/null +++ b/api/connector/simpleconnector_test.go @@ -0,0 +1,101 @@ +// Copyright 2024 Canonical Ltd. +// Licensed under the AGPLv3, see LICENCE file for details. + +package connector + +import ( + "github.com/juju/juju/api" + "github.com/juju/juju/testing" + "github.com/juju/names/v5" + gc "gopkg.in/check.v1" +) + +type simpleConnectorSuite struct { + testing.BaseSuite +} + +var _ = gc.Suite(&simpleConnectorSuite{}) + +func (s *simpleConnectorSuite) TestNewSimpleRespectsClientCredentials(c *gc.C) { + tests := []struct { + name string + opts SimpleConfig + expectedError string + expectedAPIInfo api.Info + expectedDefaultDialOpts func() api.DialOpts + }{ + { + name: "with username/password", + opts: SimpleConfig{ + ControllerAddresses: []string{"some.host:9999"}, + ModelUUID: "some-uuid", + Username: "some-username", + Password: "some-password", + }, + expectedAPIInfo: api.Info{ + Addrs: []string{"some.host:9999"}, + ModelTag: names.NewModelTag("some-uuid"), + Tag: names.NewUserTag("some-username"), + Password: "some-password", + }, + }, + { + name: "with client credentials", + opts: SimpleConfig{ + ControllerAddresses: []string{"some.host:9999"}, + ModelUUID: "some-uuid", + ClientID: "some-client-id", + ClientSecret: "some-client-secret", + }, + expectedAPIInfo: api.Info{ + Addrs: []string{"some.host:9999"}, + ModelTag: names.NewModelTag("some-uuid"), + }, + expectedDefaultDialOpts: func() api.DialOpts { + expected := api.DefaultDialOpts() + expected.LoginProvider = api.NewClientCredentialsLoginProvider("some-client-id", "some-client-secret") + return expected + }, + }, + { + name: "with username/password and client credentials; client credentials should take over", + opts: SimpleConfig{ + ControllerAddresses: []string{"some.host:9999"}, + ModelUUID: "some-uuid", + Username: "some-username", + Password: "some-password", + ClientID: "some-client-id", + ClientSecret: "some-client-secret", + }, + expectedAPIInfo: api.Info{ + Addrs: []string{"some.host:9999"}, + ModelTag: names.NewModelTag("some-uuid"), + }, + expectedDefaultDialOpts: func() api.DialOpts { + expected := api.DefaultDialOpts() + expected.LoginProvider = api.NewClientCredentialsLoginProvider("some-client-id", "some-client-secret") + return expected + }, + }, + } + + for _, test := range tests { + c.Logf("running test %s", test.name) + + connector, err := NewSimple(test.opts) + + if test.expectedError != "" { + c.Assert(err, gc.Equals, test.expectedError) + c.Assert(connector, gc.IsNil) + } else { + c.Assert(err, gc.IsNil) + c.Assert(connector.info, gc.DeepEquals, test.expectedAPIInfo) + + expectedDefaultDialOpts := api.DefaultDialOpts() + if test.expectedDefaultDialOpts != nil { + expectedDefaultDialOpts = test.expectedDefaultDialOpts() + } + c.Assert(connector.defaultDialOpts, gc.DeepEquals, expectedDefaultDialOpts) + } + } +} From eee53d5964d3c05b8a63b20f2666dedb3c61314d Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Wed, 1 May 2024 15:35:47 +0100 Subject: [PATCH 04/16] Order imports Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/api/connector/simpleconnector_test.go b/api/connector/simpleconnector_test.go index 05e9fb0dfb4..fae9596f48c 100644 --- a/api/connector/simpleconnector_test.go +++ b/api/connector/simpleconnector_test.go @@ -4,10 +4,11 @@ package connector import ( - "github.com/juju/juju/api" - "github.com/juju/juju/testing" "github.com/juju/names/v5" gc "gopkg.in/check.v1" + + "github.com/juju/juju/api" + "github.com/juju/juju/testing" ) type simpleConnectorSuite struct { From c02205442d3575888098111ffb33ffe5b0088c33 Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Tue, 7 May 2024 10:01:31 +0100 Subject: [PATCH 05/16] Check against (non-)empty username Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/api/connector/simpleconnector.go b/api/connector/simpleconnector.go index 21ef0874c5a..50390ce745f 100644 --- a/api/connector/simpleconnector.go +++ b/api/connector/simpleconnector.go @@ -53,13 +53,11 @@ func NewSimple(opts SimpleConfig, dialOptions ...api.DialOption) (*SimpleConnect ModelTag: names.NewModelTag(opts.ModelUUID), } - isClientCredentialsProvided := opts.ClientID != "" && opts.ClientSecret != "" - // When the client intends to login via client credentials (like a service // account) they leave `SimpleConfig.Username` empty and assign the client // credentials to `SimpleConfig.ClientID` and `SimpleConfig.ClientSecret`. // In such cases, assigning a user tag to `info.Tag` will result in panic. - if !isClientCredentialsProvided { + if opts.Username != "" { info.Tag = names.NewUserTag(opts.Username) info.Password = opts.Password info.Macaroons = opts.Macaroons @@ -70,7 +68,7 @@ func NewSimple(opts SimpleConfig, dialOptions ...api.DialOption) (*SimpleConnect } dialOpts := api.DefaultDialOpts() - if isClientCredentialsProvided { + if opts.Username == "" { dialOpts.LoginProvider = api.NewClientCredentialsLoginProvider( opts.ClientID, opts.ClientSecret, From 04dea43ea032c9417cfcd15ff2f4c7d8580bab09 Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Tue, 7 May 2024 10:02:17 +0100 Subject: [PATCH 06/16] Update tests to verify username/password precedence Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector_test.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/api/connector/simpleconnector_test.go b/api/connector/simpleconnector_test.go index fae9596f48c..138a6630049 100644 --- a/api/connector/simpleconnector_test.go +++ b/api/connector/simpleconnector_test.go @@ -59,7 +59,7 @@ func (s *simpleConnectorSuite) TestNewSimpleRespectsClientCredentials(c *gc.C) { }, }, { - name: "with username/password and client credentials; client credentials should take over", + name: "with username/password and client credentials; username/password takes over", opts: SimpleConfig{ ControllerAddresses: []string{"some.host:9999"}, ModelUUID: "some-uuid", @@ -71,11 +71,8 @@ func (s *simpleConnectorSuite) TestNewSimpleRespectsClientCredentials(c *gc.C) { expectedAPIInfo: api.Info{ Addrs: []string{"some.host:9999"}, ModelTag: names.NewModelTag("some-uuid"), - }, - expectedDefaultDialOpts: func() api.DialOpts { - expected := api.DefaultDialOpts() - expected.LoginProvider = api.NewClientCredentialsLoginProvider("some-client-id", "some-client-secret") - return expected + Tag: names.NewUserTag("some-username"), + Password: "some-password", }, }, } From edca96449643e31b0fbc05443258fa410d8100fb Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Tue, 7 May 2024 11:51:22 +0100 Subject: [PATCH 07/16] Assign `info.Tag` to client ID when username is empty Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/api/connector/simpleconnector.go b/api/connector/simpleconnector.go index 50390ce745f..99f59ecc8bd 100644 --- a/api/connector/simpleconnector.go +++ b/api/connector/simpleconnector.go @@ -4,6 +4,7 @@ package connector import ( + "github.com/juju/errors" "github.com/juju/names/v5" "gopkg.in/macaroon.v2" @@ -56,11 +57,16 @@ func NewSimple(opts SimpleConfig, dialOptions ...api.DialOption) (*SimpleConnect // When the client intends to login via client credentials (like a service // account) they leave `SimpleConfig.Username` empty and assign the client // credentials to `SimpleConfig.ClientID` and `SimpleConfig.ClientSecret`. - // In such cases, assigning a user tag to `info.Tag` will result in panic. + // To ensure that `info.Tag` is never empty, we should assign it with + // username or client ID, whichever is not empty. if opts.Username != "" { info.Tag = names.NewUserTag(opts.Username) info.Password = opts.Password info.Macaroons = opts.Macaroons + } else if opts.ClientID != "" { + info.Tag = names.NewUserTag(opts.ClientID) + } else { + return nil, errors.New("either Username or ClientID should be set") } if err := info.Validate(); err != nil { From b8d556f34ae7fb1a27ae3e8a1bd79ac9299037ec Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Tue, 7 May 2024 11:51:50 +0100 Subject: [PATCH 08/16] Verify returned error when neither username nor client ID are set Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector_test.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/api/connector/simpleconnector_test.go b/api/connector/simpleconnector_test.go index 138a6630049..4fd426fd750 100644 --- a/api/connector/simpleconnector_test.go +++ b/api/connector/simpleconnector_test.go @@ -51,6 +51,7 @@ func (s *simpleConnectorSuite) TestNewSimpleRespectsClientCredentials(c *gc.C) { expectedAPIInfo: api.Info{ Addrs: []string{"some.host:9999"}, ModelTag: names.NewModelTag("some-uuid"), + Tag: names.NewUserTag("some-client-id"), }, expectedDefaultDialOpts: func() api.DialOpts { expected := api.DefaultDialOpts() @@ -75,6 +76,14 @@ func (s *simpleConnectorSuite) TestNewSimpleRespectsClientCredentials(c *gc.C) { Password: "some-password", }, }, + { + name: "with neither username nre client id", + opts: SimpleConfig{ + ControllerAddresses: []string{"some.host:9999"}, + ModelUUID: "some-uuid", + }, + expectedError: "either Username or ClientID should be set", + }, } for _, test := range tests { @@ -83,7 +92,7 @@ func (s *simpleConnectorSuite) TestNewSimpleRespectsClientCredentials(c *gc.C) { connector, err := NewSimple(test.opts) if test.expectedError != "" { - c.Assert(err, gc.Equals, test.expectedError) + c.Assert(err, gc.ErrorMatches, test.expectedError) c.Assert(connector, gc.IsNil) } else { c.Assert(err, gc.IsNil) From 53fd398a15febc19d7b97df65aa48b7205c353d6 Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Tue, 7 May 2024 12:01:48 +0100 Subject: [PATCH 09/16] Fix typo Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/connector/simpleconnector_test.go b/api/connector/simpleconnector_test.go index 4fd426fd750..d8357934603 100644 --- a/api/connector/simpleconnector_test.go +++ b/api/connector/simpleconnector_test.go @@ -77,7 +77,7 @@ func (s *simpleConnectorSuite) TestNewSimpleRespectsClientCredentials(c *gc.C) { }, }, { - name: "with neither username nre client id", + name: "with neither username nor client id", opts: SimpleConfig{ ControllerAddresses: []string{"some.host:9999"}, ModelUUID: "some-uuid", From b301e2d3a0990c72a45ce9c78922bf8ef270cfd1 Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Thu, 9 May 2024 09:04:27 +0100 Subject: [PATCH 10/16] Revert making user tag from client ID Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/api/connector/simpleconnector.go b/api/connector/simpleconnector.go index 99f59ecc8bd..94ab62b9dfc 100644 --- a/api/connector/simpleconnector.go +++ b/api/connector/simpleconnector.go @@ -55,17 +55,14 @@ func NewSimple(opts SimpleConfig, dialOptions ...api.DialOption) (*SimpleConnect } // When the client intends to login via client credentials (like a service - // account) they leave `SimpleConfig.Username` empty and assign the client - // credentials to `SimpleConfig.ClientID` and `SimpleConfig.ClientSecret`. - // To ensure that `info.Tag` is never empty, we should assign it with - // username or client ID, whichever is not empty. + // account) they leave `opts.Username` empty and assign the client + // credentials to `opts.ClientID` and `opts.ClientSecret`. In such cases, + // we shouldn't assign `info.Tag` with a user tag. if opts.Username != "" { info.Tag = names.NewUserTag(opts.Username) info.Password = opts.Password info.Macaroons = opts.Macaroons - } else if opts.ClientID != "" { - info.Tag = names.NewUserTag(opts.ClientID) - } else { + } else if opts.ClientID == "" { return nil, errors.New("either Username or ClientID should be set") } From 3a306b63d6dc50b2c814be8f427e732abe4a5c97 Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Thu, 9 May 2024 09:05:09 +0100 Subject: [PATCH 11/16] Assert tag is not assigned with client ID Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/api/connector/simpleconnector_test.go b/api/connector/simpleconnector_test.go index d8357934603..5fd61302fff 100644 --- a/api/connector/simpleconnector_test.go +++ b/api/connector/simpleconnector_test.go @@ -51,7 +51,6 @@ func (s *simpleConnectorSuite) TestNewSimpleRespectsClientCredentials(c *gc.C) { expectedAPIInfo: api.Info{ Addrs: []string{"some.host:9999"}, ModelTag: names.NewModelTag("some-uuid"), - Tag: names.NewUserTag("some-client-id"), }, expectedDefaultDialOpts: func() api.DialOpts { expected := api.DefaultDialOpts() From eda28181eced913375a6e3c47201d02312544ae4 Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Thu, 9 May 2024 09:13:06 +0100 Subject: [PATCH 12/16] Remove extra empty check on client-id --- api/connector/simpleconnector.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/api/connector/simpleconnector.go b/api/connector/simpleconnector.go index 94ab62b9dfc..7e651af63c3 100644 --- a/api/connector/simpleconnector.go +++ b/api/connector/simpleconnector.go @@ -4,7 +4,6 @@ package connector import ( - "github.com/juju/errors" "github.com/juju/names/v5" "gopkg.in/macaroon.v2" @@ -62,8 +61,6 @@ func NewSimple(opts SimpleConfig, dialOptions ...api.DialOption) (*SimpleConnect info.Tag = names.NewUserTag(opts.Username) info.Password = opts.Password info.Macaroons = opts.Macaroons - } else if opts.ClientID == "" { - return nil, errors.New("either Username or ClientID should be set") } if err := info.Validate(); err != nil { From 0ea52baa47b1e954298b6555af3be938783048b7 Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Thu, 9 May 2024 09:14:26 +0100 Subject: [PATCH 13/16] Assign login provider when client ID/secret are set Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/connector/simpleconnector.go b/api/connector/simpleconnector.go index 7e651af63c3..761ae6d43e0 100644 --- a/api/connector/simpleconnector.go +++ b/api/connector/simpleconnector.go @@ -68,7 +68,7 @@ func NewSimple(opts SimpleConfig, dialOptions ...api.DialOption) (*SimpleConnect } dialOpts := api.DefaultDialOpts() - if opts.Username == "" { + if opts.ClientID != "" && opts.ClientSecret != "" { dialOpts.LoginProvider = api.NewClientCredentialsLoginProvider( opts.ClientID, opts.ClientSecret, From 34f278db9a1cee451c6f32a195b663c6e4f7fda5 Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Thu, 9 May 2024 09:14:49 +0100 Subject: [PATCH 14/16] Update tests to match latest changes Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector_test.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/api/connector/simpleconnector_test.go b/api/connector/simpleconnector_test.go index 5fd61302fff..5fa1a7a9ce1 100644 --- a/api/connector/simpleconnector_test.go +++ b/api/connector/simpleconnector_test.go @@ -74,14 +74,11 @@ func (s *simpleConnectorSuite) TestNewSimpleRespectsClientCredentials(c *gc.C) { Tag: names.NewUserTag("some-username"), Password: "some-password", }, - }, - { - name: "with neither username nor client id", - opts: SimpleConfig{ - ControllerAddresses: []string{"some.host:9999"}, - ModelUUID: "some-uuid", + expectedDefaultDialOpts: func() api.DialOpts { + expected := api.DefaultDialOpts() + expected.LoginProvider = api.NewClientCredentialsLoginProvider("some-client-id", "some-client-secret") + return expected }, - expectedError: "either Username or ClientID should be set", }, } From aa2895fed97c7eb908cfef45c51313192233357a Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Fri, 10 May 2024 09:41:53 +0100 Subject: [PATCH 15/16] Assert `Username` and `ClientID` are mutually exclusive Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/api/connector/simpleconnector.go b/api/connector/simpleconnector.go index 761ae6d43e0..b23d41c755d 100644 --- a/api/connector/simpleconnector.go +++ b/api/connector/simpleconnector.go @@ -4,6 +4,7 @@ package connector import ( + "github.com/juju/errors" "github.com/juju/names/v5" "gopkg.in/macaroon.v2" @@ -47,6 +48,12 @@ var _ Connector = (*SimpleConnector)(nil) // connect according to the specified options. If some options are invalid an // error is returned. func NewSimple(opts SimpleConfig, dialOptions ...api.DialOption) (*SimpleConnector, error) { + if opts.Username == "" && opts.ClientID == "" { + return nil, errors.New("one of Username or ClientID must be set") + } else if opts.Username != "" && opts.ClientID != "" { + return nil, errors.New("only one of Username or ClientID should be set") + } + info := api.Info{ Addrs: opts.ControllerAddresses, CACert: opts.CACert, From bc493e5e8dfe1991735aa72755748d6dd22ba2ed Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Fri, 10 May 2024 09:42:32 +0100 Subject: [PATCH 16/16] Add test cases for invalid `Username`/`ClientID` combinations Signed-off-by: Babak K. Shandiz --- api/connector/simpleconnector_test.go | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/api/connector/simpleconnector_test.go b/api/connector/simpleconnector_test.go index 5fa1a7a9ce1..4ca120f41e1 100644 --- a/api/connector/simpleconnector_test.go +++ b/api/connector/simpleconnector_test.go @@ -59,7 +59,7 @@ func (s *simpleConnectorSuite) TestNewSimpleRespectsClientCredentials(c *gc.C) { }, }, { - name: "with username/password and client credentials; username/password takes over", + name: "with both username and client ID", opts: SimpleConfig{ ControllerAddresses: []string{"some.host:9999"}, ModelUUID: "some-uuid", @@ -68,17 +68,15 @@ func (s *simpleConnectorSuite) TestNewSimpleRespectsClientCredentials(c *gc.C) { ClientID: "some-client-id", ClientSecret: "some-client-secret", }, - expectedAPIInfo: api.Info{ - Addrs: []string{"some.host:9999"}, - ModelTag: names.NewModelTag("some-uuid"), - Tag: names.NewUserTag("some-username"), - Password: "some-password", - }, - expectedDefaultDialOpts: func() api.DialOpts { - expected := api.DefaultDialOpts() - expected.LoginProvider = api.NewClientCredentialsLoginProvider("some-client-id", "some-client-secret") - return expected + expectedError: "only one of Username or ClientID should be set", + }, + { + name: "with neither username nor client ID", + opts: SimpleConfig{ + ControllerAddresses: []string{"some.host:9999"}, + ModelUUID: "some-uuid", }, + expectedError: "one of Username or ClientID must be set", }, }