Delay new auth token retrieval until it is really necessary

This commit is contained in:
Juan Carlos Mejías Rodríguez 2019-08-02 14:21:50 -04:00
parent 04a05fad86
commit 00439cc1c1
2 changed files with 59 additions and 28 deletions

View File

@ -14,10 +14,15 @@ var loginCmd = &cobra.Command{
Short: "Log in to a Portainer instance", Short: "Log in to a Portainer instance",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// Get auth token // Get auth token
client, err := common.GetClient() client, err := common.NewClient(common.ClientConfig{
Url: viper.GetString("url"),
User: viper.GetString("user"),
Password: viper.GetString("password"),
DoNotUseToken: true,
})
common.CheckError(err) common.CheckError(err)
authToken, err := client.Authenticate(viper.GetString("url"), viper.GetString("password")) authToken, err := client.Authenticate()
common.CheckError(err) common.CheckError(err)
if viper.GetBool("login.print") { if viper.GetBool("login.print") {

View File

@ -17,19 +17,23 @@ import (
var client *PortainerClient var client *PortainerClient
type clientConfig struct { type ClientConfig struct {
Url string Url string
User string User string
Password string Password string
Token string Token string
Insecure bool DoNotUseToken bool
Timeout time.Duration Insecure bool
Timeout time.Duration
} }
type PortainerClient struct { type PortainerClient struct {
http.Client http.Client
url *url.URL url *url.URL
token string user string
password string
token string
doNotUseToken bool
} }
// Check if an http.Response object has errors // Check if an http.Response object has errors
@ -73,7 +77,19 @@ func (n *PortainerClient) do(uri, method string, request io.Reader, requestType
req.Header.Set("Content-Type", requestType) req.Header.Set("Content-Type", requestType)
} }
if n.token != "" { if !n.doNotUseToken {
if n.token == "" {
clientClone, cloneErr := n.Clone()
if cloneErr != nil {
return resp, cloneErr
}
clientClone.doNotUseToken = true
n.token, err = clientClone.Authenticate()
if err != nil {
return
}
PrintDebug(fmt.Sprintf("Auth token: %s", n.token))
}
req.Header.Set("Authorization", "Bearer "+n.token) req.Header.Set("Authorization", "Bearer "+n.token)
} }
@ -123,12 +139,12 @@ func (n *PortainerClient) doJSON(uri, method string, request interface{}, respon
} }
// Authenticate a user to get an auth token // Authenticate a user to get an auth token
func (n *PortainerClient) Authenticate(user, password string) (token string, err error) { func (n *PortainerClient) Authenticate() (token string, err error) {
PrintVerbose("Getting auth token...") PrintVerbose("Getting auth token...")
reqBody := AuthenticateUserRequest{ reqBody := AuthenticateUserRequest{
Username: user, Username: n.user,
Password: password, Password: n.password,
} }
respBody := AuthenticateUserResponse{} respBody := AuthenticateUserResponse{}
@ -247,15 +263,35 @@ func (n *PortainerClient) GetStatus() (status Status, err error) {
return return
} }
// Get a clone of the client
func (n *PortainerClient) Clone() (c *PortainerClient, err error) {
c = &PortainerClient{
url: n.url,
user: n.user,
password: n.password,
token: n.token,
doNotUseToken: n.doNotUseToken,
}
c.Timeout = n.Timeout
c.Transport = n.Transport
return
}
// Create a new client // Create a new client
func newClient(config clientConfig) (c *PortainerClient, err error) { func NewClient(config ClientConfig) (c *PortainerClient, err error) {
apiUrl, err := url.Parse(config.Url + "/api/") apiUrl, err := url.Parse(config.Url + "/api/")
if err != nil { if err != nil {
return return
} }
c = &PortainerClient{ c = &PortainerClient{
url: apiUrl, url: apiUrl,
user: config.User,
password: config.Password,
token: config.Token,
} }
c.Timeout = config.Timeout c.Timeout = config.Timeout
@ -266,23 +302,13 @@ func newClient(config clientConfig) (c *PortainerClient, err error) {
}, },
} }
if config.Token != "" {
c.token = config.Token
} else {
c.token, err = c.Authenticate(config.User, config.Password)
if err != nil {
return nil, err
}
PrintDebug(fmt.Sprintf("Auth token: %s", c.token))
}
return return
} }
// Get the cached client or a new one // Get the cached client or a new one
func GetClient() (c *PortainerClient, err error) { func GetClient() (c *PortainerClient, err error) {
if client == nil { if client == nil {
client, err = newClient(clientConfig{ client, err = NewClient(ClientConfig{
Url: viper.GetString("url"), Url: viper.GetString("url"),
User: viper.GetString("user"), User: viper.GetString("user"),
Password: viper.GetString("password"), Password: viper.GetString("password"),