Skip to content
This repository has been archived by the owner on Nov 8, 2022. It is now read-only.

Commit

Permalink
Created V2 API routes for Metric and Tasks:
Browse files Browse the repository at this point in the history
        - V2 metrics routes now have a metrics section in the body of the response.
        - Fixed text case in v2/tests from "ScheduledTasks" to "scheduled_tasks" to be consistent with other responses.
        - Added V2 folders in rest and in rbody to hold v2 methods
  • Loading branch information
kjlyon committed Oct 4, 2016
1 parent 87ab47c commit 9921521
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 6 deletions.
17 changes: 12 additions & 5 deletions mgmt/rest/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (

"github.com/intelsdi-x/snap/core"
"github.com/intelsdi-x/snap/mgmt/rest/rbody"
apiV2 "github.com/intelsdi-x/snap/mgmt/rest/v2"
)

func (s *Server) getMetrics(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
Expand All @@ -40,6 +41,7 @@ func (s *Server) getMetrics(w http.ResponseWriter, r *http.Request, _ httprouter
// perform a query
q := r.URL.Query()
v := q.Get("ver")
apiVersion := r.URL.Path[1:3]
ns_query := q.Get("ns")
if ns_query != "" {
ver = 0 // 0: get all versions
Expand All @@ -62,7 +64,7 @@ func (s *Server) getMetrics(w http.ResponseWriter, r *http.Request, _ httprouter
respond(404, rbody.FromError(err), w)
return
}
respondWithMetrics(r.Host, mets, w)
respondWithMetrics(r.Host, mets, w, apiVersion)
return
}

Expand All @@ -71,7 +73,7 @@ func (s *Server) getMetrics(w http.ResponseWriter, r *http.Request, _ httprouter
respond(500, rbody.FromError(err), w)
return
}
respondWithMetrics(r.Host, mets, w)
respondWithMetrics(r.Host, mets, w, apiVersion)
}

func (s *Server) getMetricsFromTree(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
Expand All @@ -94,6 +96,7 @@ func (s *Server) getMetricsFromTree(w http.ResponseWriter, r *http.Request, para
)
q := r.URL.Query()
v := q.Get("ver")
apiVersion := r.URL.Path[1:3]

if ns[len(ns)-1] == "*" {
if v == "" {
Expand All @@ -111,7 +114,7 @@ func (s *Server) getMetricsFromTree(w http.ResponseWriter, r *http.Request, para
respond(404, rbody.FromError(err), w)
return
}
respondWithMetrics(r.Host, mets, w)
respondWithMetrics(r.Host, mets, w, apiVersion)
return
}

Expand All @@ -122,7 +125,7 @@ func (s *Server) getMetricsFromTree(w http.ResponseWriter, r *http.Request, para
respond(404, rbody.FromError(err), w)
return
}
respondWithMetrics(r.Host, mets, w)
respondWithMetrics(r.Host, mets, w, apiVersion)
return
}

Expand Down Expand Up @@ -171,7 +174,11 @@ func (s *Server) getMetricsFromTree(w http.ResponseWriter, r *http.Request, para
respond(200, b, w)
}

func respondWithMetrics(host string, mets []core.CatalogedMetric, w http.ResponseWriter) {
func respondWithMetrics(host string, mets []core.CatalogedMetric, w http.ResponseWriter, version string) {
if version == "v2" {
apiV2.RespondWithMetrics(host, mets, w)
return
}
b := rbody.NewMetricsReturned()

for _, met := range mets {
Expand Down
49 changes: 49 additions & 0 deletions mgmt/rest/rbody/v2/metric.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package v2

import (
"fmt"

"github.com/intelsdi-x/snap/mgmt/rest/rbody"
)

type MetricList struct {
Metrics []rbody.Metric `json:"metrics,omitempty"`
}

type MetricReturned struct {
Metric *rbody.Metric `json:"metric,omitempty"`
}

func (m *MetricReturned) ResponseBodyMessage() string {
return "Metric returned"
}

func (m *MetricReturned) ResponseBodyType() string {
return "metric_returned"
}

type MetricsReturned MetricList

func (m MetricsReturned) Len() int {
return len(m.Metrics)
}

func (m MetricsReturned) Less(i, j int) bool {
return (fmt.Sprintf("%s:%d", m.Metrics[i].Namespace, m.Metrics[i].Version)) < (fmt.Sprintf("%s:%d", m.Metrics[j].Namespace, m.Metrics[j].Version))
}

func (m MetricsReturned) Swap(i, j int) {
m.Metrics[i], m.Metrics[j] = m.Metrics[j], m.Metrics[i]
}

func NewMetricsReturned() MetricsReturned {
return MetricsReturned{Metrics: []rbody.Metric{}}
}

func (m MetricsReturned) ResponseBodyMessage() string {
return "Metrics returned"
}

func (m MetricsReturned) ResponseBodyType() string {
return rbody.MetricsReturnedType
}
27 changes: 27 additions & 0 deletions mgmt/rest/rbody/v2/task.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package v2

import "github.com/intelsdi-x/snap/mgmt/rest/rbody"

type ScheduledTaskListReturned struct {
ScheduledTasks []rbody.ScheduledTask `json:"scheduled_task,omitempty"`
}

func (s *ScheduledTaskListReturned) Len() int {
return len(s.ScheduledTasks)
}

func (s *ScheduledTaskListReturned) Less(i, j int) bool {
return s.ScheduledTasks[j].CreationTime().After(s.ScheduledTasks[i].CreationTime())
}

func (s *ScheduledTaskListReturned) Swap(i, j int) {
s.ScheduledTasks[i], s.ScheduledTasks[j] = s.ScheduledTasks[j], s.ScheduledTasks[i]
}

func (s *ScheduledTaskListReturned) ResponseBodyMessage() string {
return "Scheduled tasks retrieved"
}

func (s *ScheduledTaskListReturned) ResponseBodyType() string {
return "scheduled_task_list_returned"
}
1 change: 0 additions & 1 deletion mgmt/rest/rest_v1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ func startV1API(cfg *mockConfig, testType string) *restAPIInstance {
mockTaskManager := &fixtures.MockTaskManager{}
r.BindTaskManager(mockTaskManager)
}

go func(ch <-chan error) {
// Block on the error channel. Will return exit status 1 for an error or
// just return if the channel closes.
Expand Down
5 changes: 5 additions & 0 deletions mgmt/rest/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -470,8 +470,13 @@ func (s *Server) addRoutes() {
s.r.GET("/v1/metrics", s.getMetrics)
s.r.GET("/v1/metrics/*namespace", s.getMetricsFromTree)

s.r.GET("/v2/metrics", s.getMetrics)
s.r.GET("/v2/metrics/*namespace", s.getMetricsFromTree)

// task routes
s.r.GET("/v1/tasks", s.getTasks)
s.r.GET("/v2/tasks", s.getTasks)

s.r.GET("/v1/tasks/:id", s.getTask)
s.r.GET("/v1/tasks/:id/watch", s.watchTask)
s.r.POST("/v1/tasks", s.addTask)
Expand Down
6 changes: 6 additions & 0 deletions mgmt/rest/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"time"

log "github.com/Sirupsen/logrus"
apiV2 "github.com/intelsdi-x/snap/mgmt/rest/v2"
"github.com/julienschmidt/httprouter"

"github.com/intelsdi-x/snap/core"
Expand Down Expand Up @@ -56,6 +57,11 @@ func (s *Server) addTask(w http.ResponseWriter, r *http.Request, _ httprouter.Pa

func (s *Server) getTasks(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
sts := s.mt.GetTasks()
apiVersion := r.URL.Path[1:3]
if apiVersion == "v2" {
apiV2.GetTasks(w, r, sts)
return
}

tasks := &rbody.ScheduledTaskListReturned{}
tasks.ScheduledTasks = make([]rbody.ScheduledTask, len(sts))
Expand Down
92 changes: 92 additions & 0 deletions mgmt/rest/v2/metric.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package v2

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/url"
"sort"

"github.com/codegangsta/negroni"
"github.com/intelsdi-x/snap/core"
"github.com/intelsdi-x/snap/mgmt/rest/rbody"
"github.com/intelsdi-x/snap/mgmt/rest/rbody/v2"
)

func RespondWithMetrics(host string, mets []core.CatalogedMetric, w http.ResponseWriter) {
b := v2.NewMetricsReturned()

for _, met := range mets {
rt := met.Policy().RulesAsTable()
policies := make([]rbody.PolicyTable, 0, len(rt))
for _, r := range rt {
policies = append(policies, rbody.PolicyTable{
Name: r.Name,
Type: r.Type,
Default: r.Default,
Required: r.Required,
Minimum: r.Minimum,
Maximum: r.Maximum,
})
}
dyn, indexes := met.Namespace().IsDynamic()
var dynamicElements []rbody.DynamicElement
if dyn {
dynamicElements = getDynamicElements(met.Namespace(), indexes)
}

b.Metrics = append(b.Metrics, rbody.Metric{
Namespace: met.Namespace().String(),
Version: met.Version(),
LastAdvertisedTimestamp: met.LastAdvertisedTime().Unix(),
Description: met.Description(),
Dynamic: dyn,
DynamicElements: dynamicElements,
Unit: met.Unit(),
Policy: policies,
Href: catalogedMetricURI(host, met),
})
}
sort.Sort(b)
respond(200, b, w)
}

func catalogedMetricURI(host string, mt core.CatalogedMetric) string {
return fmt.Sprintf("%s://%s/v1/metrics?ns=%s&ver=%d", "http", host, url.QueryEscape(mt.Namespace().String()), mt.Version())
}

func getDynamicElements(ns core.Namespace, indexes []int) []rbody.DynamicElement {
elements := make([]rbody.DynamicElement, 0, len(indexes))
for _, v := range indexes {
e := ns.Element(v)
elements = append(elements, rbody.DynamicElement{
Index: v,
Name: e.Name,
Description: e.Description,
})
}
return elements
}

func respond(code int, b rbody.Body, w http.ResponseWriter) {
resp := &rbody.APIResponse{
Meta: &rbody.APIResponseMeta{
Code: code,
Message: b.ResponseBodyMessage(),
Type: b.ResponseBodyType(),
Version: 2,
},
Body: b,
}
if !w.(negroni.ResponseWriter).Written() {
w.WriteHeader(code)
}

j, err := json.MarshalIndent(resp, "", " ")
if err != nil {
panic(err)
}
j = bytes.Replace(j, []byte("\\u0026"), []byte("&"), -1)
fmt.Fprint(w, string(j))
}
29 changes: 29 additions & 0 deletions mgmt/rest/v2/task.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package v2

import (
"fmt"
"net/http"
"sort"

"github.com/intelsdi-x/snap/core"
"github.com/intelsdi-x/snap/mgmt/rest/rbody"
"github.com/intelsdi-x/snap/mgmt/rest/rbody/v2"
)

func GetTasks(w http.ResponseWriter, r *http.Request, sts map[string]core.Task) {
tasks := &v2.ScheduledTaskListReturned{}
tasks.ScheduledTasks = make([]rbody.ScheduledTask, len(sts))

i := 0
for _, t := range sts {
tasks.ScheduledTasks[i] = *rbody.SchedulerTaskFromTask(t)
tasks.ScheduledTasks[i].Href = taskURI(r.Host, t)
i++
}
sort.Sort(tasks)
respond(200, tasks, w)
}

func taskURI(host string, t core.Task) string {
return fmt.Sprintf("%s://%s/v1/tasks/%s", "http", host, t.ID())
}

0 comments on commit 9921521

Please sign in to comment.