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

Add pool statistics #3

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Deleting...
Status: 204 No Content
```

## Supported Resources
## Supported Configuration Resources

Support for resources is being added as needed.

Expand Down Expand Up @@ -97,3 +97,28 @@ Support for resources is being added as needed.
- [ ] User Authenticator
- [ ] User Group
- [x] Virtual Server

## Supported Statistics Resources
- [ ] Actions
- [ ] Bandwidth
- [ ] Cache
- [ ] Cloud API Credentials
- [ ] Connection Rate Limit
- [ ] Events
- [ ] Extras
- [ ] GLB Services
- [ ] Globals
- [ ] Listen IPs
- [ ] Locations
- [ ] Network Interface
- [ ] Nodes
- [ ] Per-location Service
- [ ] Per Node SLM
- [x] Pools
- [ ] Rule Authenticators
- [ ] Rules
- [ ] Service Level Monitors
- [ ] Service Protection
- [ ] SSL OCSP Stapling
- [ ] Traffic IPs
- [ ] Virtual Servers
2 changes: 1 addition & 1 deletion action.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

type Action struct {
jsonResource `json:"-"`
jsonConfigResource `json:"-"`
ActionProperties `json:"properties"`
}

Expand Down
2 changes: 1 addition & 1 deletion event_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

type EventType struct {
jsonResource `json:"-"`
jsonConfigResource `json:"-"`
EventTypeProperties `json:"properties"`
}

Expand Down
2 changes: 1 addition & 1 deletion file.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package stingray

// fileResource represents a file resource.
type fileResource struct {
resource
configResource
Content []byte
Note string
}
Expand Down
14 changes: 11 additions & 3 deletions json_resource.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
package stingray

// jsonResource represents a JSON resource.
type jsonResource struct {
resource
type jsonConfigResource struct {
configResource
}

func (f *jsonResource) contentType() string {
func (f *jsonConfigResource) contentType() string {
return "application/json"
}

type jsonStatsResource struct {
statsResource
}

func (f *jsonStatsResource) contentType() string {
return "application/json"
}
2 changes: 1 addition & 1 deletion monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

// A Monitor is a Stingray monitor.
type Monitor struct {
jsonResource `json:"-"`
jsonConfigResource `json:"-"`
MonitorProperties `json:"properties"`
}

Expand Down
2 changes: 1 addition & 1 deletion pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

// A Pool is a Stingray pool.
type Pool struct {
jsonResource `json:"-"`
jsonConfigResource `json:"-"`
PoolProperties `json:"properties"`
}

Expand Down
72 changes: 72 additions & 0 deletions pool_stats.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package stingray

import (
"encoding/json"
"net/http"
)

// A PoolStats is a Stingray pool.
type PoolStats struct {
jsonStatsResource `json:"-"`
PoolStatistics `json:"statistics"`
}

type PoolStatistics struct {
Algorithm string `json:"algorithm"`
BytesIn int64 `json:"bytes_in"`
BytesInHigh uint32 `json:"bytes_in_hi"`
BytesInLow uint32 `json:"bytes_in_low"`
BytesOut int64 `json:"bytes_out"`
BytesOutHigh uint32 `json:"bytes_out_hi"`
BytesOutLow uint32 `json:"bytes_out_low"`
ConnectionsQueued int `json:"conns_queued"`
DisabledNodeCount int `json:"disabled"`
DrainingNodeCount int `json:"draining"`
MaxQueueTime int `json:"max_queue_time"`
MeanQueueTime int `json:"mean_queue_time"`
MinQueueTime int `json:"min_queue_time"`
NodeCount int `json:"nodes"`
SessionPersistence string `json:"persistence"`
QueueTimeouts int `json:"queue_timeouts"`
SessionsMigrated int `json:"session_migrated"`
State string `json:"state"`
TotalConnections int `json:"total_conn"`
}

func (r *PoolStats) endpoint() string {
return "pools"
}


//String will return back the json as a string
func (r *PoolStats) String() string {
b := r.Bytes()
return string(b)
}

//Bytes will return back just the bytes
func (r *PoolStats) Bytes() []byte {
b, _ := jsonMarshal(r)
return b
}

func (r *PoolStats) decode(data []byte) error {
return json.Unmarshal(data, &r)
}

func NewPoolStats(name string) *PoolStats {
r := new(PoolStats)
r.setName(name)
return r
}

func (c *Client) GetPoolStats(name string) (*PoolStats, *http.Response, error) {
r := NewPoolStats(name)

resp, err := c.Get(r)
if err != nil {
return nil, resp, err
}

return r, resp, nil
}
2 changes: 1 addition & 1 deletion protection.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

type Protection struct {
jsonResource `json:"-"`
jsonConfigResource `json:"-"`
ProtectionProperties `json:"properties"`
}

Expand Down
2 changes: 1 addition & 1 deletion rate.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

// A Rate is a Stingray rate shaping class.
type Rate struct {
jsonResource `json:"-"`
jsonConfigResource `json:"-"`
RateProperties `json:"properties"`
}

Expand Down
26 changes: 23 additions & 3 deletions resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,40 @@ type Resourcer interface {
Name() string
setName(string)
endpoint() string
pathType() pathType
contentType() string
decode([]byte) error
Bytes() []byte
}

type resource struct {
type baseResource struct {
name string
contentType string
}

func (r *resource) Name() string {

func (r *baseResource) Name() string {
return r.name
}

func (r *resource) setName(name string) {
func (r *baseResource) setName(name string) {
r.name = name
}


type configResource struct {
baseResource
}

func (r *configResource) pathType() pathType {
return configPath
}

type statsResource struct {
baseResource
}

func (r *statsResource) pathType() pathType {
return statsPath
}

2 changes: 1 addition & 1 deletion service_level_monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

// A ServiceLevelMonitor is a Stingray service level monitor.
type ServiceLevelMonitor struct {
jsonResource `json:"-"`
jsonConfigResource `json:"-"`
ServiceLevelMonitorProperties `json:"properties"`
}

Expand Down
2 changes: 1 addition & 1 deletion ssl_server_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

// A SSLServerKey is a Stingray trusted certificate.
type SSLServerKey struct {
jsonResource `json:"-"`
jsonConfigResource `json:"-"`
SSLServerKeyProperties `json:"properties"`
}

Expand Down
63 changes: 48 additions & 15 deletions stingray.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,36 @@ import (
"io/ioutil"
"net/http"
"net/url"
"errors"
)

const (
basePath = "/api/tm/3.5/config/active/"
baseConfigPath = "/api/tm/3.5/config/active/"
baseStatsPath = "/api/tm/3.5/status/local_tm/statistics/"
)

type pathType int
const (
configPath pathType = iota
statsPath
)

// A Client manages communication with the Stingray API.
type Client struct {
// HTTP client used to communicate with the API.
Client *http.Client
Client *http.Client

// API base URL for configuration namespace
configURL *url.URL

// API base URL
BaseURL *url.URL
// API base URL for stats namespace
statsURL *url.URL

// Username used for communicating with the API.
Username string
Username string

// Password used for communicating with the API.
Password string
Password string
}

// NewClient returns a new Stingray API client, using the supplied
Expand All @@ -36,15 +47,23 @@ func NewClient(httpClient *http.Client, urlStr, username string, password string
httpClient = http.DefaultClient
}

u, _ := url.Parse(urlStr)
if u.Path == "" {
rel, _ := url.Parse(basePath)
u = u.ResolveReference(rel)
cu, _ := url.Parse(urlStr)
su := cu
var relStats *url.URL
if cu.Path == "" {
rel, _ := url.Parse(baseConfigPath)
cu = cu.ResolveReference(rel)
relStats, _ = url.Parse(baseStatsPath)
} else {
statsRelPath := "../../status/local_tm/statistics/"
relStats, _ = url.Parse(statsRelPath)
}
su = su.ResolveReference(relStats)

c := &Client{
Client: httpClient,
BaseURL: u,
configURL: cu,
statsURL: su,
Username: username,
Password: password,
}
Expand All @@ -54,20 +73,34 @@ func NewClient(httpClient *http.Client, urlStr, username string, password string

// NewRequest creates a new request with the params
func (c *Client) NewRequest(method, urlStr string, body *[]byte) (*http.Request, error) {
return c.doMakeRequest(configPath, method, urlStr, body)
}

func (c *Client) doMakeRequest(pathType pathType, method, urlStr string, body *[]byte) (*http.Request, error) {
var bodyreader io.Reader
var baseUrl *url.URL

if body != nil {
bodyreader = bytes.NewReader(*body)
}

rel, err := url.Parse(c.BaseURL.Path + urlStr)
rel, err := url.Parse(urlStr)
if err != nil {
return nil, err
}

u := c.BaseURL.ResolveReference(rel)
switch pathType {
case configPath:
baseUrl = c.configURL
break
case statsPath:
baseUrl = c.statsURL
break
default:
return nil, errors.New("Tried to make request with an unknown path type")
}

u := baseUrl.ResolveReference(rel)
req, err := http.NewRequest(method, u.String(), bodyreader)
if err != nil {
return nil, err
Expand Down Expand Up @@ -97,9 +130,10 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) {

// Get retrieves a resource
func (c *Client) Get(r Resourcer) (*http.Response, error) {

u := fmt.Sprintf("%v/%v", r.endpoint(), r.Name())

req, err := c.NewRequest("GET", u, nil)
req, err := c.doMakeRequest(r.pathType(), "GET", u, nil)
if err != nil {
return nil, err
}
Expand All @@ -108,7 +142,6 @@ func (c *Client) Get(r Resourcer) (*http.Response, error) {
if err != nil {
return resp, err
}

body, err := ioutil.ReadAll(resp.Body)
defer resp.Body.Close()
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions stingray_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ func TestNewClient(t *testing.T) {
t.Errorf("NewClient Client is nil")
}

if c.BaseURL.String() != url {
t.Errorf("NewClient URL = %v, want %v", c.BaseURL.String(), url)
if c.configURL.String() != url {
t.Errorf("NewClient URL = %v, want %v", c.configURL.String(), url)
}

if c.Username != username {
Expand Down
Loading