github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/connector/clientstoreconnector.go (about) 1 // Copyright 2022 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package connector 5 6 import ( 7 "errors" 8 9 "github.com/go-macaroon-bakery/macaroon-bakery/v3/httpbakery" 10 11 "github.com/juju/juju/api" 12 "github.com/juju/juju/juju" 13 "github.com/juju/juju/jujuclient" 14 ) 15 16 var ErrEmptyControllerName = errors.New("empty controller name") 17 18 // A Connector can provie api.Connection instances based on a ClientStore 19 type ClientStoreConnector struct { 20 config ClientStoreConfig 21 defaultDialOpts api.DialOpts 22 } 23 24 var _ Connector = (*ClientStoreConnector)(nil) 25 26 // ClientStoreConfig provides configuration for a Connector. 27 type ClientStoreConfig struct { 28 // Controller to connect to. Required 29 ControllerName string 30 31 // Model to connect to. Optional 32 ModelUUID string 33 34 // Defaults to the file client store 35 ClientStore jujuclient.ClientStore 36 37 // Defaults to the user for the controller 38 AccountDetails *jujuclient.AccountDetails 39 } 40 41 // NewClientStore returns a new *ClientStoreConnector instance for the given config, or an error if 42 // there was a problem setting up the connector. 43 func NewClientStore(config ClientStoreConfig, dialOptions ...api.DialOption) (*ClientStoreConnector, error) { 44 if config.ControllerName == "" { 45 return nil, ErrEmptyControllerName 46 } 47 if config.ClientStore == nil { 48 config.ClientStore = jujuclient.NewFileClientStore() 49 } 50 if config.AccountDetails == nil { 51 d, err := config.ClientStore.AccountDetails(config.ControllerName) 52 if err != nil { 53 return nil, err 54 } 55 config.AccountDetails = d 56 } 57 conn := &ClientStoreConnector{ 58 config: config, 59 defaultDialOpts: api.DefaultDialOpts(), 60 } 61 for _, opt := range dialOptions { 62 opt(&conn.defaultDialOpts) 63 } 64 return conn, nil 65 } 66 67 // Connect returns an api.Connection to the controller / model specified in c's 68 // config, or an error if there was a problem opening the connection. 69 func (c *ClientStoreConnector) Connect(dialOptions ...api.DialOption) (api.Connection, error) { 70 opts := c.defaultDialOpts 71 for _, f := range dialOptions { 72 f(&opts) 73 } 74 75 // By default there is no bakery client in the dial options, so we reproduce 76 // behaviour that is scattered around the code to obtain a bakery client 77 // with a cookie jar from the client store. 78 jar, err := c.config.ClientStore.CookieJar(c.config.ControllerName) 79 if err != nil { 80 return nil, err 81 } 82 83 bakeryClient := httpbakery.NewClient() 84 bakeryClient.Jar = jar 85 opts.BakeryClient = bakeryClient 86 87 return juju.NewAPIConnection(juju.NewAPIConnectionParams{ 88 ControllerName: c.config.ControllerName, 89 Store: c.config.ClientStore, 90 OpenAPI: api.Open, 91 DialOpts: opts, 92 AccountDetails: c.config.AccountDetails, 93 ModelUUID: c.config.ModelUUID, 94 }) 95 }