diff --git a/control/plugin/cpolicy/float.go b/control/plugin/cpolicy/float.go index d666b415b..fa35f08fd 100644 --- a/control/plugin/cpolicy/float.go +++ b/control/plugin/cpolicy/float.go @@ -45,12 +45,16 @@ func (f *FloatRule) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Key string `json:"key"` Required bool `json:"required"` - Default ctypes.ConfigValue `json:"default"` + Default ctypes.ConfigValue `json:"default,omitempty"` + Minimum ctypes.ConfigValue `json:"minimum,omitempty"` + Maximum ctypes.ConfigValue `json:"maximum,omitempty"` Type string `json:"type"` }{ Key: f.key, Required: f.required, Default: f.Default(), + Minimum: f.Minimum(), + Maximum: f.Maximum(), Type: "float", }) } @@ -191,3 +195,17 @@ func (f *FloatRule) SetMinimum(m float64) { func (f *FloatRule) SetMaximum(m float64) { f.maximum = &m } + +func (i *FloatRule) Minimum() ctypes.ConfigValue { + if i.minimum != nil { + return &ctypes.ConfigValueFloat{Value: *i.minimum} + } + return nil +} + +func (i *FloatRule) Maximum() ctypes.ConfigValue { + if i.maximum != nil { + return &ctypes.ConfigValueFloat{Value: *i.maximum} + } + return nil +} diff --git a/control/plugin/cpolicy/integer.go b/control/plugin/cpolicy/integer.go index cf743f726..3d8fb2976 100644 --- a/control/plugin/cpolicy/integer.go +++ b/control/plugin/cpolicy/integer.go @@ -68,12 +68,16 @@ func (i *IntRule) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Key string `json:"key"` Required bool `json:"required"` - Default ctypes.ConfigValue `json:"default"` + Default ctypes.ConfigValue `json:"default,omitempty"` + Minimum ctypes.ConfigValue `json:"minimum,omitempty"` + Maximum ctypes.ConfigValue `json:"maximum,omitempty"` Type string `json:"type"` }{ Key: i.key, Required: i.required, Default: i.Default(), + Minimum: i.Minimum(), + Maximum: i.Maximum(), Type: "integer", }) } @@ -194,3 +198,17 @@ func (i *IntRule) SetMinimum(m int) { func (i *IntRule) SetMaximum(m int) { i.maximum = &m } + +func (i *IntRule) Minimum() ctypes.ConfigValue { + if i.minimum != nil { + return &ctypes.ConfigValueInt{Value: *i.minimum} + } + return nil +} + +func (i *IntRule) Maximum() ctypes.ConfigValue { + if i.maximum != nil { + return &ctypes.ConfigValueInt{Value: *i.maximum} + } + return nil +} diff --git a/control/plugin/cpolicy/node.go b/control/plugin/cpolicy/node.go index e5e4e9af5..f695dee4e 100644 --- a/control/plugin/cpolicy/node.go +++ b/control/plugin/cpolicy/node.go @@ -128,6 +128,8 @@ type RuleTable struct { Type string Default interface{} Required bool + Minimum interface{} + Maximum interface{} } func (p *ConfigPolicyNode) RulesAsTable() []RuleTable { @@ -141,6 +143,8 @@ func (p *ConfigPolicyNode) RulesAsTable() []RuleTable { Type: r.Type(), Default: r.Default(), Required: r.Required(), + Minimum: r.Minimum(), + Maximum: r.Maximum(), }) } return rt @@ -220,6 +224,16 @@ func addRulesToConfigPolicyNode(rules map[string]interface{}, cpn *ConfigPolicyN def := int(def_) r.default_ = &def } + if m, ok := rule["minimum"]; ok { + min_, _ := m.(float64) + min := int(min_) + r.minimum = &min + } + if m, ok := rule["maximum"]; ok { + max_, _ := m.(float64) + max := int(max_) + r.maximum = &max + } cpn.Add(r) case "string": r, _ := NewStringRule(k, req) @@ -237,6 +251,14 @@ func addRulesToConfigPolicyNode(rules map[string]interface{}, cpn *ConfigPolicyN def, _ := d.(float64) r.default_ = &def } + if m, ok := rule["minimum"]; ok { + min, _ := m.(float64) + r.minimum = &min + } + if m, ok := rule["maximum"]; ok { + max, _ := m.(float64) + r.maximum = &max + } cpn.Add(r) default: return errors.New("unknown type") diff --git a/control/plugin/cpolicy/node_test.go b/control/plugin/cpolicy/node_test.go index a3ede41dd..2e1be8d00 100644 --- a/control/plugin/cpolicy/node_test.go +++ b/control/plugin/cpolicy/node_test.go @@ -136,4 +136,103 @@ func TestConfigPolicyNode(t *testing.T) { So(m2, ShouldBeNil) }) + Convey("Test integer value between minimum and maximum for rule succeeds", t, func() { + n := NewPolicyNode() + + m := map[string]ctypes.ConfigValue{} + m["port"] = ctypes.ConfigValueInt{Value: 5} + + r1, _ := NewIntegerRule("port", false) + r1.SetMinimum(0) + r1.SetMaximum(10) + + n.Add(r1) + + m2, pe := n.Process(m) + + So(len(pe.Errors()), ShouldEqual, 0) + So((*m2)["port"].(ctypes.ConfigValueInt).Value, ShouldEqual, 5) + }) + Convey("Test integer value outside of maximum for rule fails", t, func() { + n := NewPolicyNode() + + m := map[string]ctypes.ConfigValue{} + m["port"] = ctypes.ConfigValueInt{Value: 5} + + r1, _ := NewIntegerRule("port", false) + r1.SetMinimum(0) + r1.SetMaximum(4) + + n.Add(r1) + + _, pe := n.Process(m) + + So(len(pe.Errors()), ShouldEqual, 1) + }) + Convey("Test integer value outside of minimum for rule fails", t, func() { + n := NewPolicyNode() + + m := map[string]ctypes.ConfigValue{} + m["port"] = ctypes.ConfigValueInt{Value: 5} + + r1, _ := NewIntegerRule("port", false) + r1.SetMinimum(7) + r1.SetMaximum(100) + + n.Add(r1) + + _, pe := n.Process(m) + + So(len(pe.Errors()), ShouldEqual, 1) + }) + Convey("Test float value between minimum and maximum for rule succeeds", t, func() { + n := NewPolicyNode() + + m := map[string]ctypes.ConfigValue{} + m["num"] = ctypes.ConfigValueFloat{Value: 5.06} + + r1, _ := NewFloatRule("num", false) + r1.SetMinimum(3.14) + r1.SetMaximum(10.17) + + n.Add(r1) + + m2, pe := n.Process(m) + + So(len(pe.Errors()), ShouldEqual, 0) + So((*m2)["num"].(ctypes.ConfigValueFloat).Value, ShouldEqual, 5.06) + }) + Convey("Test float value outside of maximum for rule fails", t, func() { + n := NewPolicyNode() + + m := map[string]ctypes.ConfigValue{} + m["num"] = ctypes.ConfigValueFloat{Value: 5.97} + + r1, _ := NewFloatRule("num", false) + r1.SetMinimum(0) + r1.SetMaximum(3.14) + + n.Add(r1) + + _, pe := n.Process(m) + + So(len(pe.Errors()), ShouldEqual, 1) + }) + Convey("Test float value outside of minimum for rule fails", t, func() { + n := NewPolicyNode() + + m := map[string]ctypes.ConfigValue{} + m["num"] = ctypes.ConfigValueFloat{Value: 2.26} + + r1, _ := NewFloatRule("num", false) + r1.SetMinimum(3.14) + r1.SetMaximum(42) + + n.Add(r1) + + _, pe := n.Process(m) + + So(len(pe.Errors()), ShouldEqual, 1) + }) + } diff --git a/control/plugin/cpolicy/rule.go b/control/plugin/cpolicy/rule.go index 435a7ef29..6e63401ac 100644 --- a/control/plugin/cpolicy/rule.go +++ b/control/plugin/cpolicy/rule.go @@ -39,6 +39,8 @@ type Rule interface { Default() ctypes.ConfigValue Required() bool Type() string + Minimum() ctypes.ConfigValue + Maximum() ctypes.ConfigValue } type rule struct { diff --git a/control/plugin/cpolicy/string.go b/control/plugin/cpolicy/string.go index ae6a05711..621d07dba 100644 --- a/control/plugin/cpolicy/string.go +++ b/control/plugin/cpolicy/string.go @@ -139,3 +139,11 @@ func (s *StringRule) Default() ctypes.ConfigValue { func (s *StringRule) Required() bool { return s.required } + +func (s *StringRule) Minimum() ctypes.ConfigValue { + return nil +} + +func (s *StringRule) Maximum() ctypes.ConfigValue { + return nil +} diff --git a/mgmt/rest/metric.go b/mgmt/rest/metric.go index f729ba360..a72a984fd 100644 --- a/mgmt/rest/metric.go +++ b/mgmt/rest/metric.go @@ -88,6 +88,8 @@ func (s *Server) getMetricsFromTree(w http.ResponseWriter, r *http.Request, para Type: r.Type, Default: r.Default, Required: r.Required, + Minimum: r.Minimum, + Maximum: r.Maximum, }) } mb.Policy = policies @@ -107,6 +109,8 @@ func respondWithMetrics(mets []core.CatalogedMetric, w http.ResponseWriter) { Type: r.Type, Default: r.Default, Required: r.Required, + Minimum: r.Minimum, + Maximum: r.Maximum, }) } b = append(b, rbody.Metric{ diff --git a/mgmt/rest/rbody/metric.go b/mgmt/rest/rbody/metric.go index a71d80f71..c3253c8ca 100644 --- a/mgmt/rest/rbody/metric.go +++ b/mgmt/rest/rbody/metric.go @@ -29,8 +29,10 @@ const ( type PolicyTable struct { Name string `json:"name"` Type string `json:"type"` - Default interface{} `json:"default"` + Default interface{} `json:"default,omitempty"` Required bool `json:"required"` + Minimum interface{} `json:"minimum,omitempty"` + Maximum interface{} `json:"maximum,omitempty"` } type Metric struct {