Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle workspace in Kong's client #62

Merged
merged 15 commits into from
Jun 7, 2021
46 changes: 37 additions & 9 deletions kong/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/http/httputil"
"net/url"
"os"
"sync"
"time"

"github.com/pkg/errors"
Expand Down Expand Up @@ -37,7 +38,9 @@ var (
// Kong cluster
type Client struct {
client *http.Client
baseURL string
mmorel-35 marked this conversation as resolved.
Show resolved Hide resolved
defaultRootURL string
workspace string // Do not access directly. Use Get/SetWorkspace().
mmorel-35 marked this conversation as resolved.
Show resolved Hide resolved
workspaceLock sync.RWMutex // Synchronizes access to workspace.
common service
Consumers AbstractConsumerService
Developers AbstractDeveloperService
Expand Down Expand Up @@ -117,7 +120,7 @@ func NewClient(baseURL *string, client *http.Client) (*Client, error) {
if err != nil {
return nil, errors.Wrap(err, "parsing URL")
}
kong.baseURL = url.String()
kong.defaultRootURL = url.String()

kong.common.client = kong
kong.Consumers = (*ConsumerService)(&kong.common)
Expand Down Expand Up @@ -164,6 +167,29 @@ func NewClient(baseURL *string, client *http.Client) (*Client, error) {
return kong, nil
}

// SetWorkspace sets the Kong Enteprise workspace in the client.
// Calling this function with an empty string resets the workspace to default workspace.
func (c *Client) SetWorkspace(workspace string) {
c.workspaceLock.Lock()
defer c.workspaceLock.Unlock()
c.workspace = workspace
}

//Workspace return the workspace
func (c *Client) Workspace() string {
c.workspaceLock.RLock()
defer c.workspaceLock.RUnlock()
return c.workspace
}

// baseURL build the base URL from the rootURL and the workspace
func (c *Client) baseURL(workspace string) string {
mmorel-35 marked this conversation as resolved.
Show resolved Hide resolved
if len(workspace) > 0 {
return c.defaultRootURL + "/" + workspace
}
return c.defaultRootURL
}

// Do executes a HTTP request and returns a response
func (c *Client) Do(ctx context.Context, req *http.Request,
v interface{}) (*Response, error) {
Expand Down Expand Up @@ -280,18 +306,20 @@ func (c *Client) Status(ctx context.Context) (*Status, error) {
return &s, nil
}

// Root returns the response of GET request on root of
// Admin API (GET /).
// Root returns the response of GET request on root of Admin API (GET / or /kong with a workspace).
func (c *Client) Root(ctx context.Context) (map[string]interface{}, error) {
req, err := c.NewRequest("GET", "/", nil, nil)
endpoint := "/"
if len(c.Workspace()) > 0 {
endpoint = "/kong"
}
req, err := c.NewRequest("GET", endpoint, nil, nil)
mmorel-35 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}

var root map[string]interface{}
_, err = c.Do(ctx, req, &root)
var info map[string]interface{}
_, err = c.Do(ctx, req, &info)
if err != nil {
return nil, err
}
return root, nil
return info, nil
}
20 changes: 12 additions & 8 deletions kong/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,9 @@ import (
"github.com/google/go-querystring/query"
)

// NewRequest creates a request based on the inputs.
// endpoint should be relative to the baseURL specified during
// client creation.
// body is always marshaled into JSON.
func (c *Client) NewRequest(method, endpoint string, qs interface{},
//NewRequestRaw creates a request based on the inputs.
func (c *Client) NewRequestRaw(method, baseURL string, endpoint string, qs interface{},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we rename baseURL to url?
I think it makes the signature a bit more clear.

Copy link
Contributor Author

@mmorel-35 mmorel-35 May 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using url would mean using the full one, isn't it?
As it's always concatenated with the endpoint parameter, wouldn't it lead to confusion?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I misunderstood. @mflendrich Should we name these as NewWorkspacedRequest NewRequest and then appropriate docs comment? The current API in this patch is not very easy to grok.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to achieve two results:

  • no breaking changes to NewRequest
  • having a new function that accepts the base URL from the outside

Maybe we can relax the former. In that situation, we could do the following movements:

  • rename NewRequest to NewRequestCurrentWorkspace
  • rename NewRequestRaw to NewRequestForBaseURL and say explicitly in the docstring that this expects the workspace URL to be passed as the base URL.

WDYT?

body interface{}) (*http.Request, error) {

if endpoint == "" {
return nil, errors.New("endpoint can't be nil")
}
Expand All @@ -30,8 +26,7 @@ func (c *Client) NewRequest(method, endpoint string, qs interface{},
}

//Create a new request
req, err := http.NewRequest(method, c.baseURL+endpoint,
bytes.NewBuffer(buf))
req, err := http.NewRequest(method, baseURL+endpoint, bytes.NewBuffer(buf))
if err != nil {
return nil, err
}
Expand All @@ -51,3 +46,12 @@ func (c *Client) NewRequest(method, endpoint string, qs interface{},
}
return req, nil
}

// NewRequest creates a request based on the inputs.
// endpoint should be relative to the baseURL specified during
// client creation.
// body is always marshaled into JSON.
func (c *Client) NewRequest(method, endpoint string, qs interface{},
body interface{}) (*http.Request, error) {
Comment on lines +54 to +55
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a bit more descriptive?

Suggested change
func (c *Client) NewRequest(method, endpoint string, qs interface{},
body interface{}) (*http.Request, error) {
func (c *Client) NewRequest(method, relativePath string, qs interface{},
body interface{}) (*http.Request, error) {

return c.NewRequestRaw(method, c.baseURL(c.GetWorkspace()), endpoint, qs, body)
}