Skip to content

Commit

Permalink
Merge pull request kubernetes#11395 from akutz/feature/boskos-acquire…
Browse files Browse the repository at this point in the history
…-wait

boskos-client: AcquireWait/AcquireByStateWait
  • Loading branch information
k8s-ci-robot authored Feb 21, 2019
2 parents fd689b0 + be21778 commit d6a7b26
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 3 deletions.
23 changes: 22 additions & 1 deletion boskos/client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,22 @@ The client object looks like:

```
type Client struct {
// RetryCount is the number of times an HTTP request issued by this client
// is retried when the initial request fails due an inaccessible endpoint.
RetryCount uint
// RetryDuration is the interval to wait before retrying an HTTP operation
// that failed due to an inaccessible endpoint.
RetryWait time.Duration
url string
resources []string
owner string
}
```

To create a boskos client, use NewClient func, specify boskos server url, and owner of the client:
To create a boskos client, use `NewClient` and specify the Boskos endpoint URL and resource owner.
The `NewClient` function also sets the client's `RetryCount` to `3` and `RetryWait` interval to `10s`.
```
func NewClient(url string, owner string) *Client
```
Expand All @@ -30,6 +39,18 @@ func NewClient(url string, owner string) *Client
// Acquire asks boskos for a resource of certain type in certain state, and set the resource to dest state.
func (c *Client) Acquire(rtype string, state string, dest string) (string, error)
// AcquireWait blocks until Acquire returns the specified resource or the
// provided context is cancelled or its deadline exceeded.
func (c *Client) AcquireWait(rtype string, state string, dest string) (string, error)
// AcquireByState asks boskos for a resources of certain type, and set the resource to dest state.
// Returns a list of resources on success.
func (c *Client) AcquireByState(state, dest string, names []string) ([]common.Resource, error)
// AcquireByStateWait blocks until AcquireByState returns the specified
// resource(s) or the provided context is cancelled or its deadline exceeded.
func (c *Client) AcquireByStateWait(ctx context.Context, state, dest string, names []string) ([]common.Resource, error)
// ReleaseAll returns all resources hold by the client back to boskos and set them to dest state.
func (c *Client) ReleaseAll(dest string) error
Expand Down
61 changes: 59 additions & 2 deletions boskos/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ var (
ErrNotFound = errors.New("resources not found")
// ErrAlreadyInUse is returned by Acquire when resources are already being requested.
ErrAlreadyInUse = errors.New("resources already used by another user")
// ErrContextRequired is returned by AcquireWait and AcquireByStateWait when
// they are invoked with a nil context.
ErrContextRequired = errors.New("context required")
)

// Client defines the public Boskos client object
Expand Down Expand Up @@ -120,6 +123,31 @@ func (c *Client) Acquire(rtype, state, dest string) (*common.Resource, error) {
return r, nil
}

// AcquireWait blocks until Acquire returns the specified resource or the
// provided context is cancelled or its deadline exceeded.
func (c *Client) AcquireWait(ctx context.Context, rtype, state, dest string) (*common.Resource, error) {
if ctx == nil {
return nil, ErrContextRequired
}
// Try to acquire the resource until available or the context is
// cancelled or its deadline exceeded.
for {
r, err := c.Acquire(rtype, state, dest)
if err != nil {
if err == ErrAlreadyInUse || err == ErrNotFound {
select {
case <-ctx.Done():
return nil, err
case <-time.After(3 * time.Second):
continue
}
}
return nil, err
}
return r, nil
}
}

// AcquireByState asks boskos for a resources of certain type, and set the resource to dest state.
// Returns a list of resources on success.
func (c *Client) AcquireByState(state, dest string, names []string) ([]common.Resource, error) {
Expand All @@ -135,6 +163,32 @@ func (c *Client) AcquireByState(state, dest string, names []string) ([]common.Re
return resources, nil
}

// AcquireByStateWait blocks until AcquireByState returns the specified
// resource(s) or the provided context is cancelled or its deadline
// exceeded.
func (c *Client) AcquireByStateWait(ctx context.Context, state, dest string, names []string) ([]common.Resource, error) {
if ctx == nil {
return nil, ErrContextRequired
}
// Try to acquire the resource(s) until available or the context is
// cancelled or its deadline exceeded.
for {
r, err := c.AcquireByState(state, dest, names)
if err != nil {
if err == ErrAlreadyInUse || err == ErrNotFound {
select {
case <-ctx.Done():
return nil, err
case <-time.After(3 * time.Second):
continue
}
}
return nil, err
}
return r, nil
}
}

// ReleaseAll returns all resources hold by the client back to boskos and set them to dest state.
func (c *Client) ReleaseAll(dest string) error {
c.lock.Lock()
Expand Down Expand Up @@ -286,7 +340,8 @@ func (c *Client) acquire(rtype, state, dest string) (*common.Resource, error) {
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusOK {
switch resp.StatusCode {
case http.StatusOK:
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
Expand All @@ -301,7 +356,9 @@ func (c *Client) acquire(rtype, state, dest string) (*common.Resource, error) {
return nil, fmt.Errorf("unable to parse resource")
}
return &res, nil
} else if resp.StatusCode == http.StatusNotFound {
case http.StatusUnauthorized:
return nil, ErrAlreadyInUse
case http.StatusNotFound:
return nil, ErrNotFound
}
return nil, fmt.Errorf("status %s, status code %v", resp.Status, resp.StatusCode)
Expand Down

0 comments on commit d6a7b26

Please sign in to comment.