diff --git a/control/plugin/cpolicy/node.go b/control/plugin/cpolicy/node.go index 2c7b2799f..77e09a57e 100644 --- a/control/plugin/cpolicy/node.go +++ b/control/plugin/cpolicy/node.go @@ -119,16 +119,18 @@ func (p *ConfigPolicyNode) Add(rules ...Rule) { } } +type RuleTableSlice []RuleTable + type RuleTable struct { - Name string - Type string - Default interface{} - Required bool - Minimum interface{} - Maximum interface{} + Name string `json:"name"` + Type string `json:"type"` + Default interface{} `json:"default,omitempty"` + Required bool `json:"required"` + Minimum interface{} `json:"minimum,omitempty"` + Maximum interface{} `json:"maximum,omitempty"` } -func (p *ConfigPolicyNode) RulesAsTable() []RuleTable { +func (p *ConfigPolicyNode) RulesAsTable() RuleTableSlice { p.mutex.Lock() defer p.mutex.Unlock() diff --git a/mgmt/rest/fixtures/mock_tribe_manager.go b/mgmt/rest/fixtures/mock_tribe_manager.go index 21c6c7829..ac9f591d0 100644 --- a/mgmt/rest/fixtures/mock_tribe_manager.go +++ b/mgmt/rest/fixtures/mock_tribe_manager.go @@ -35,6 +35,19 @@ var ( ) func init() { + mockTribeMember = agreement.NewMember(&memberlist.Node{ + Name: "Imma_Mock", + Addr: net.ParseIP("193.11.22.11"), + Port: uint16(0), + Meta: []byte("meta"), // Metadata from the delegate for this node. + PMin: uint8(0), // Minimum protocol version this understands + PMax: uint8(0), // Maximum protocol version this understands + PCur: uint8(0), // Current version node is speaking + DMin: uint8(0), // Min protocol version for the delegate to understand + DMax: uint8(0), // Max protocol version for the delegate to understand + DCur: uint8(0), // Current version delegate is speaking + }) + mockTribeAgreement = agreement.New("Agree1") mockTribeAgreement.PluginAgreement.Add( agreement.Plugin{Name_: "mockVersion", Version_: 1, Type_: core.CollectorPluginType}) @@ -80,7 +93,7 @@ func (m *MockTribeManager) GetMembers() []string { return []string{"one", "two", "three"} } func (m *MockTribeManager) GetMember(name string) *agreement.Member { - return &agreement.Member{} + return mockTribeMember } // These constants are the expected tribe responses from running @@ -209,7 +222,7 @@ const ( "version": 1 }, "body": { - "name": "", + "name": "Imma_Mock", "plugin_agreement": "", "tags": null, "task_agreements": null diff --git a/mgmt/rest/metric.go b/mgmt/rest/metric.go index 46a684cef..05f9e7f9c 100644 --- a/mgmt/rest/metric.go +++ b/mgmt/rest/metric.go @@ -41,6 +41,8 @@ func (s *Server) getMetrics(w http.ResponseWriter, r *http.Request, _ httprouter // perform a query q := r.URL.Query() v := q.Get("ver") + // apiVersion should be "v1" or "v2". + // If apiVersion != "v2" calls default to V1 functionality apiVersion := r.URL.Path[1:3] ns_query := q.Get("ns") if ns_query != "" { @@ -59,21 +61,21 @@ func (s *Server) getMetrics(w http.ResponseWriter, r *http.Request, _ httprouter ns = ns[:len(ns)-1] } - mets, err := s.mm.FetchMetrics(core.NewNamespace(ns...), ver) + mts, err := s.mm.FetchMetrics(core.NewNamespace(ns...), ver) if err != nil { respond(404, rbody.FromError(err), w) return } - respondWithMetrics(r.Host, mets, w, apiVersion) + respondWithMetrics(r.Host, mts, w, apiVersion) return } - mets, err := s.mm.MetricCatalog() + mts, err := s.mm.MetricCatalog() if err != nil { respond(500, rbody.FromError(err), w) return } - respondWithMetrics(r.Host, mets, w, apiVersion) + respondWithMetrics(r.Host, mts, w, apiVersion) } func (s *Server) getMetricsFromTree(w http.ResponseWriter, r *http.Request, params httprouter.Params) { @@ -96,6 +98,8 @@ func (s *Server) getMetricsFromTree(w http.ResponseWriter, r *http.Request, para ) q := r.URL.Query() v := q.Get("ver") + // apiVersion should be "v1" or "v2". + // If apiVersion != "v2" calls default to V1 functionality apiVersion := r.URL.Path[1:3] if ns[len(ns)-1] == "*" { @@ -109,23 +113,23 @@ func (s *Server) getMetricsFromTree(w http.ResponseWriter, r *http.Request, para } } - mets, err := s.mm.FetchMetrics(core.NewNamespace(ns[:len(ns)-1]...), ver) + mts, err := s.mm.FetchMetrics(core.NewNamespace(ns[:len(ns)-1]...), ver) if err != nil { respond(404, rbody.FromError(err), w) return } - respondWithMetrics(r.Host, mets, w, apiVersion) + respondWithMetrics(r.Host, mts, w, apiVersion) return } // If no version was given, get all version that fall at this namespace. if v == "" { - mets, err := s.mm.FetchMetrics(core.NewNamespace(ns...), 0) + mts, err := s.mm.FetchMetrics(core.NewNamespace(ns...), 0) if err != nil { respond(404, rbody.FromError(err), w) return } - respondWithMetrics(r.Host, mets, w, apiVersion) + respondWithMetrics(r.Host, mts, w, apiVersion) return } @@ -157,58 +161,35 @@ func (s *Server) getMetricsFromTree(w http.ResponseWriter, r *http.Request, para LastAdvertisedTimestamp: mt.LastAdvertisedTime().Unix(), Href: catalogedMetricURI(r.Host, mt), } - rt := mt.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, - }) - } + policies := rbody.PolicyTableSlice(mt.Policy().RulesAsTable()) mb.Policy = policies b.Metric = mb respond(200, b, w) } -func respondWithMetrics(host string, mets []core.CatalogedMetric, w http.ResponseWriter, version string) { +func respondWithMetrics(host string, mts []core.CatalogedMetric, w http.ResponseWriter, version string) { if version == "v2" { - apiV2.RespondWithMetrics(host, mets, w) + apiV2.RespondWithMetrics(host, mts, w) return } b := rbody.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() + for _, m := range mts { + policies := rbody.PolicyTableSlice(m.Policy().RulesAsTable()) + dyn, indexes := m.Namespace().IsDynamic() var dynamicElements []rbody.DynamicElement if dyn { - dynamicElements = getDynamicElements(met.Namespace(), indexes) + dynamicElements = getDynamicElements(m.Namespace(), indexes) } b = append(b, rbody.Metric{ - Namespace: met.Namespace().String(), - Version: met.Version(), - LastAdvertisedTimestamp: met.LastAdvertisedTime().Unix(), - Description: met.Description(), + Namespace: m.Namespace().String(), + Version: m.Version(), + LastAdvertisedTimestamp: m.LastAdvertisedTime().Unix(), + Description: m.Description(), Dynamic: dyn, DynamicElements: dynamicElements, - Unit: met.Unit(), + Unit: m.Unit(), Policy: policies, - Href: catalogedMetricURI(host, met), + Href: catalogedMetricURI(host, m), }) } sort.Sort(b) diff --git a/mgmt/rest/rbody/metric.go b/mgmt/rest/rbody/metric.go index 68d94c995..06e958cc6 100644 --- a/mgmt/rest/rbody/metric.go +++ b/mgmt/rest/rbody/metric.go @@ -19,21 +19,20 @@ limitations under the License. package rbody -import "fmt" +import ( + "fmt" + + "github.com/intelsdi-x/snap/control/plugin/cpolicy" +) const ( MetricsReturnedType = "metrics_returned" MetricReturnedType = "metric_returned" ) -type PolicyTable struct { - Name string `json:"name"` - Type string `json:"type"` - Default interface{} `json:"default,omitempty"` - Required bool `json:"required"` - Minimum interface{} `json:"minimum,omitempty"` - Maximum interface{} `json:"maximum,omitempty"` -} +type PolicyTable cpolicy.RuleTable + +type PolicyTableSlice []cpolicy.RuleTable type Metric struct { LastAdvertisedTimestamp int64 `json:"last_advertised_timestamp,omitempty"` @@ -43,7 +42,7 @@ type Metric struct { DynamicElements []DynamicElement `json:"dynamic_elements,omitempty"` Description string `json:"description,omitempty"` Unit string `json:"unit,omitempty"` - Policy []PolicyTable `json:"policy,omitempty"` + Policy PolicyTableSlice `json:"policy,omitempty"` Href string `json:"href"` } diff --git a/mgmt/rest/server.go b/mgmt/rest/server.go index 8e9957e57..aeea4e551 100644 --- a/mgmt/rest/server.go +++ b/mgmt/rest/server.go @@ -468,9 +468,9 @@ func (s *Server) addRoutes() { // metric routes 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("/v1/metrics/*namespace", s.getMetricsFromTree) s.r.GET("/v2/metrics/*namespace", s.getMetricsFromTree) // task routes @@ -488,13 +488,28 @@ func (s *Server) addRoutes() { // tribe routes if s.tr != nil { s.r.GET("/v1/tribe/agreements", s.getAgreements) + s.r.GET("/v2/tribes/agreements", s.getAgreements) + s.r.POST("/v1/tribe/agreements", s.addAgreement) + s.r.POST("/v2/tribes/agreements", s.addAgreement) + s.r.GET("/v1/tribe/agreements/:name", s.getAgreement) + s.r.GET("/v2/tribes/agreements/:name", s.getAgreement) + s.r.DELETE("/v1/tribe/agreements/:name", s.deleteAgreement) + s.r.DELETE("/v2/tribes/agreements/:name", s.deleteAgreement) + s.r.PUT("/v1/tribe/agreements/:name/join", s.joinAgreement) + s.r.PUT("/v2/tribes/agreements/:name/join", s.joinAgreement) + s.r.DELETE("/v1/tribe/agreements/:name/leave", s.leaveAgreement) + s.r.DELETE("/v2/tribes/agreements/:name/leave", s.leaveAgreement) + s.r.GET("/v1/tribe/members", s.getMembers) + s.r.GET("/v2/tribes/members", s.getMembers) + s.r.GET("/v1/tribe/member/:name", s.getMember) + s.r.GET("/v2/tribes/members/:name", s.getMember) } } diff --git a/mgmt/rest/task.go b/mgmt/rest/task.go index e1caba85c..27ba7d9ed 100644 --- a/mgmt/rest/task.go +++ b/mgmt/rest/task.go @@ -57,6 +57,8 @@ 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 should be "v1" or "v2". + // If apiVersion != "v2" calls default to V1 functionality apiVersion := r.URL.Path[1:3] if apiVersion == "v2" { apiV2.GetTasks(w, r, sts) diff --git a/mgmt/rest/v2/metric.go b/mgmt/rest/v2/metric.go index 15fe7ff66..39a61436d 100644 --- a/mgmt/rest/v2/metric.go +++ b/mgmt/rest/v2/metric.go @@ -14,38 +14,27 @@ import ( "github.com/intelsdi-x/snap/mgmt/rest/rbody/v2" ) -func RespondWithMetrics(host string, mets []core.CatalogedMetric, w http.ResponseWriter) { +func RespondWithMetrics(host string, mts []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() + for _, m := range mts { + var policies rbody.PolicyTableSlice + p := m.Policy().RulesAsTable() + policies = rbody.PolicyTableSlice(p) + dyn, indexes := m.Namespace().IsDynamic() var dynamicElements []rbody.DynamicElement if dyn { - dynamicElements = getDynamicElements(met.Namespace(), indexes) + dynamicElements = getDynamicElements(m.Namespace(), indexes) } - b.Metrics = append(b.Metrics, rbody.Metric{ - Namespace: met.Namespace().String(), - Version: met.Version(), - LastAdvertisedTimestamp: met.LastAdvertisedTime().Unix(), - Description: met.Description(), + Namespace: m.Namespace().String(), + Version: m.Version(), + LastAdvertisedTimestamp: m.LastAdvertisedTime().Unix(), + Description: m.Description(), Dynamic: dyn, DynamicElements: dynamicElements, - Unit: met.Unit(), + Unit: m.Unit(), Policy: policies, - Href: catalogedMetricURI(host, met), + Href: catalogedMetricURI(host, m), }) } sort.Sort(b)