diff --git a/Gopkg.lock b/Gopkg.lock index 508227b857..d8021c0107 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -47,6 +47,11 @@ packages = ["proto"] revision = "8ee79997227bf9b34611aee7946ae64735e6fd93" +[[projects]] + name = "github.com/google/go-cmp" + packages = ["cmp"] + revision = "79b2d888f100ec053545168aa94bcfb322e8bfc8" + [[projects]] name = "github.com/google/go-github" packages = ["github"] @@ -135,6 +140,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "bac138180cd86a0ae604cd3aa7b6ba300673478c880882bd58a4bd7f8bff518d" + inputs-digest = "f34fb88755292baba8b52c14bf5b9a028daff96a763368a7cf1de90004d33695" solver-name = "gps-cdcl" solver-version = 1 diff --git a/bolt/internal/internal.go b/bolt/internal/internal.go index b3f677c4ae..912d125618 100644 --- a/bolt/internal/internal.go +++ b/bolt/internal/internal.go @@ -181,6 +181,19 @@ func MarshalDashboard(d chronograf.Dashboard) ([]byte, error) { } } + axes := make(map[string]*Axis, len(c.Axes)) + for a, r := range c.Axes { + // need to explicitly allocate a new array because r.Bounds is + // over-written and the resulting slices from previous iterations will + // point to later iteration's data. It is _not_ enough to simply re-slice + // r.Bounds + axis := [2]int64{} + copy(axis[:], r.Bounds[:2]) + axes[a] = &Axis{ + Bounds: axis[:], + } + } + cells[i] = &DashboardCell{ ID: c.ID, X: c.X, @@ -190,6 +203,7 @@ func MarshalDashboard(d chronograf.Dashboard) ([]byte, error) { Name: c.Name, Queries: queries, Type: c.Type, + Axes: axes, } } templates := make([]*Template, len(d.Templates)) @@ -253,6 +267,13 @@ func UnmarshalDashboard(data []byte, d *chronograf.Dashboard) error { } } + axes := make(map[string]chronograf.Axis, len(c.Axes)) + for a, r := range c.Axes { + axis := chronograf.Axis{} + copy(axis.Bounds[:], r.Bounds[:2]) + axes[a] = axis + } + cells[i] = chronograf.DashboardCell{ ID: c.ID, X: c.X, @@ -262,6 +283,7 @@ func UnmarshalDashboard(data []byte, d *chronograf.Dashboard) error { Name: c.Name, Queries: queries, Type: c.Type, + Axes: axes, } } diff --git a/bolt/internal/internal.pb.go b/bolt/internal/internal.pb.go index 994617efad..eef73feb1b 100644 --- a/bolt/internal/internal.pb.go +++ b/bolt/internal/internal.pb.go @@ -12,6 +12,7 @@ It has these top-level messages: Source Dashboard DashboardCell + Axis Template TemplateValue TemplateQuery @@ -86,14 +87,15 @@ func (m *Dashboard) GetTemplates() []*Template { } type DashboardCell struct { - X int32 `protobuf:"varint,1,opt,name=x,proto3" json:"x,omitempty"` - Y int32 `protobuf:"varint,2,opt,name=y,proto3" json:"y,omitempty"` - W int32 `protobuf:"varint,3,opt,name=w,proto3" json:"w,omitempty"` - H int32 `protobuf:"varint,4,opt,name=h,proto3" json:"h,omitempty"` - Queries []*Query `protobuf:"bytes,5,rep,name=queries" json:"queries,omitempty"` - Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` - Type string `protobuf:"bytes,7,opt,name=type,proto3" json:"type,omitempty"` - ID string `protobuf:"bytes,8,opt,name=ID,proto3" json:"ID,omitempty"` + X int32 `protobuf:"varint,1,opt,name=x,proto3" json:"x,omitempty"` + Y int32 `protobuf:"varint,2,opt,name=y,proto3" json:"y,omitempty"` + W int32 `protobuf:"varint,3,opt,name=w,proto3" json:"w,omitempty"` + H int32 `protobuf:"varint,4,opt,name=h,proto3" json:"h,omitempty"` + Queries []*Query `protobuf:"bytes,5,rep,name=queries" json:"queries,omitempty"` + Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` + Type string `protobuf:"bytes,7,opt,name=type,proto3" json:"type,omitempty"` + ID string `protobuf:"bytes,8,opt,name=ID,proto3" json:"ID,omitempty"` + Axes map[string]*Axis `protobuf:"bytes,9,rep,name=axes" json:"axes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"` } func (m *DashboardCell) Reset() { *m = DashboardCell{} } @@ -108,6 +110,22 @@ func (m *DashboardCell) GetQueries() []*Query { return nil } +func (m *DashboardCell) GetAxes() map[string]*Axis { + if m != nil { + return m.Axes + } + return nil +} + +type Axis struct { + Bounds []int64 `protobuf:"varint,1,rep,name=bounds" json:"bounds,omitempty"` +} + +func (m *Axis) Reset() { *m = Axis{} } +func (m *Axis) String() string { return proto.CompactTextString(m) } +func (*Axis) ProtoMessage() {} +func (*Axis) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{3} } + type Template struct { ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` TempVar string `protobuf:"bytes,2,opt,name=temp_var,json=tempVar,proto3" json:"temp_var,omitempty"` @@ -120,7 +138,7 @@ type Template struct { func (m *Template) Reset() { *m = Template{} } func (m *Template) String() string { return proto.CompactTextString(m) } func (*Template) ProtoMessage() {} -func (*Template) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{3} } +func (*Template) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{4} } func (m *Template) GetValues() []*TemplateValue { if m != nil { @@ -145,7 +163,7 @@ type TemplateValue struct { func (m *TemplateValue) Reset() { *m = TemplateValue{} } func (m *TemplateValue) String() string { return proto.CompactTextString(m) } func (*TemplateValue) ProtoMessage() {} -func (*TemplateValue) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{4} } +func (*TemplateValue) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{5} } type TemplateQuery struct { Command string `protobuf:"bytes,1,opt,name=command,proto3" json:"command,omitempty"` @@ -159,7 +177,7 @@ type TemplateQuery struct { func (m *TemplateQuery) Reset() { *m = TemplateQuery{} } func (m *TemplateQuery) String() string { return proto.CompactTextString(m) } func (*TemplateQuery) ProtoMessage() {} -func (*TemplateQuery) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{5} } +func (*TemplateQuery) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{6} } type Server struct { ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` @@ -174,7 +192,7 @@ type Server struct { func (m *Server) Reset() { *m = Server{} } func (m *Server) String() string { return proto.CompactTextString(m) } func (*Server) ProtoMessage() {} -func (*Server) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{6} } +func (*Server) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{7} } type Layout struct { ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` @@ -187,7 +205,7 @@ type Layout struct { func (m *Layout) Reset() { *m = Layout{} } func (m *Layout) String() string { return proto.CompactTextString(m) } func (*Layout) ProtoMessage() {} -func (*Layout) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{7} } +func (*Layout) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{8} } func (m *Layout) GetCells() []*Cell { if m != nil { @@ -212,7 +230,7 @@ type Cell struct { func (m *Cell) Reset() { *m = Cell{} } func (m *Cell) String() string { return proto.CompactTextString(m) } func (*Cell) ProtoMessage() {} -func (*Cell) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{8} } +func (*Cell) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{9} } func (m *Cell) GetQueries() []*Query { if m != nil { @@ -234,7 +252,7 @@ type Query struct { func (m *Query) Reset() { *m = Query{} } func (m *Query) String() string { return proto.CompactTextString(m) } func (*Query) ProtoMessage() {} -func (*Query) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{9} } +func (*Query) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{10} } func (m *Query) GetRange() *Range { if m != nil { @@ -251,7 +269,7 @@ type Range struct { func (m *Range) Reset() { *m = Range{} } func (m *Range) String() string { return proto.CompactTextString(m) } func (*Range) ProtoMessage() {} -func (*Range) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{10} } +func (*Range) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{11} } type AlertRule struct { ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` @@ -263,7 +281,7 @@ type AlertRule struct { func (m *AlertRule) Reset() { *m = AlertRule{} } func (m *AlertRule) String() string { return proto.CompactTextString(m) } func (*AlertRule) ProtoMessage() {} -func (*AlertRule) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{11} } +func (*AlertRule) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{12} } type User struct { ID uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` @@ -273,12 +291,13 @@ type User struct { func (m *User) Reset() { *m = User{} } func (m *User) String() string { return proto.CompactTextString(m) } func (*User) ProtoMessage() {} -func (*User) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{12} } +func (*User) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{13} } func init() { proto.RegisterType((*Source)(nil), "internal.Source") proto.RegisterType((*Dashboard)(nil), "internal.Dashboard") proto.RegisterType((*DashboardCell)(nil), "internal.DashboardCell") + proto.RegisterType((*Axis)(nil), "internal.Axis") proto.RegisterType((*Template)(nil), "internal.Template") proto.RegisterType((*TemplateValue)(nil), "internal.TemplateValue") proto.RegisterType((*TemplateQuery)(nil), "internal.TemplateQuery") @@ -294,60 +313,65 @@ func init() { func init() { proto.RegisterFile("internal.proto", fileDescriptorInternal) } var fileDescriptorInternal = []byte{ - // 876 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x55, 0xdf, 0x6e, 0xe3, 0xc4, - 0x17, 0xd6, 0xc4, 0x76, 0x62, 0x9f, 0x76, 0xfb, 0xfb, 0x69, 0xb4, 0x62, 0x0d, 0xdc, 0x44, 0x16, - 0x48, 0x01, 0x89, 0x82, 0xd8, 0x27, 0x68, 0x6b, 0x09, 0x85, 0x76, 0x97, 0x32, 0x69, 0xcb, 0x15, - 0x5a, 0x4d, 0x9c, 0x93, 0xc6, 0x5a, 0x27, 0x36, 0x63, 0xbb, 0x59, 0xbf, 0x05, 0x4f, 0x80, 0x84, - 0xc4, 0x15, 0x17, 0x5c, 0xf0, 0x02, 0x3c, 0x04, 0x2f, 0x84, 0xce, 0xcc, 0xf8, 0x4f, 0xd8, 0x82, - 0xf6, 0x8a, 0xbb, 0xf9, 0xce, 0x19, 0x7f, 0xe7, 0xdf, 0x77, 0xc6, 0x70, 0x92, 0xee, 0x2a, 0x54, - 0x3b, 0x99, 0x9d, 0x16, 0x2a, 0xaf, 0x72, 0xee, 0xb7, 0x38, 0xfa, 0x6d, 0x04, 0xe3, 0x45, 0x5e, - 0xab, 0x04, 0xf9, 0x09, 0x8c, 0xe6, 0x71, 0xc8, 0xa6, 0x6c, 0xe6, 0x88, 0xd1, 0x3c, 0xe6, 0x1c, - 0xdc, 0x97, 0x72, 0x8b, 0xe1, 0x68, 0xca, 0x66, 0x81, 0xd0, 0x67, 0xb2, 0xdd, 0x34, 0x05, 0x86, - 0x8e, 0xb1, 0xd1, 0x99, 0x7f, 0x00, 0xfe, 0x6d, 0x49, 0x6c, 0x5b, 0x0c, 0x5d, 0x6d, 0xef, 0x30, - 0xf9, 0xae, 0x65, 0x59, 0xee, 0x73, 0xb5, 0x0a, 0x3d, 0xe3, 0x6b, 0x31, 0xff, 0x3f, 0x38, 0xb7, - 0xe2, 0x2a, 0x1c, 0x6b, 0x33, 0x1d, 0x79, 0x08, 0x93, 0x18, 0xd7, 0xb2, 0xce, 0xaa, 0x70, 0x32, - 0x65, 0x33, 0x5f, 0xb4, 0x90, 0x78, 0x6e, 0x30, 0xc3, 0x7b, 0x25, 0xd7, 0xa1, 0x6f, 0x78, 0x5a, - 0xcc, 0x4f, 0x81, 0xcf, 0x77, 0x25, 0x26, 0xb5, 0xc2, 0xc5, 0xeb, 0xb4, 0xb8, 0x43, 0x95, 0xae, - 0x9b, 0x30, 0xd0, 0x04, 0x8f, 0x78, 0x28, 0xca, 0x0b, 0xac, 0x24, 0xc5, 0x06, 0x4d, 0xd5, 0x42, - 0x1e, 0xc1, 0xf1, 0x62, 0x23, 0x15, 0xae, 0x16, 0x98, 0x28, 0xac, 0xc2, 0x23, 0xed, 0x3e, 0xb0, - 0x45, 0x3f, 0x32, 0x08, 0x62, 0x59, 0x6e, 0x96, 0xb9, 0x54, 0xab, 0x77, 0xea, 0xd9, 0x67, 0xe0, - 0x25, 0x98, 0x65, 0x65, 0xe8, 0x4c, 0x9d, 0xd9, 0xd1, 0x97, 0xcf, 0x4e, 0xbb, 0x61, 0x74, 0x3c, - 0x17, 0x98, 0x65, 0xc2, 0xdc, 0xe2, 0x5f, 0x40, 0x50, 0xe1, 0xb6, 0xc8, 0x64, 0x85, 0x65, 0xe8, - 0xea, 0x4f, 0x78, 0xff, 0xc9, 0x8d, 0x75, 0x89, 0xfe, 0x52, 0xf4, 0x2b, 0x83, 0x27, 0x07, 0x54, - 0xfc, 0x18, 0xd8, 0x1b, 0x9d, 0x95, 0x27, 0xd8, 0x1b, 0x42, 0x8d, 0xce, 0xc8, 0x13, 0xac, 0x21, - 0xb4, 0xd7, 0xf3, 0xf3, 0x04, 0xdb, 0x13, 0xda, 0xe8, 0xa9, 0x79, 0x82, 0x6d, 0xf8, 0x27, 0x30, - 0xf9, 0xa1, 0x46, 0x95, 0x62, 0x19, 0x7a, 0x3a, 0xf2, 0xff, 0xfa, 0xc8, 0xdf, 0xd6, 0xa8, 0x1a, - 0xd1, 0xfa, 0xa9, 0x52, 0x3d, 0x71, 0x33, 0x3e, 0x7d, 0x26, 0x5b, 0x45, 0xea, 0x98, 0x18, 0x1b, - 0x9d, 0x6d, 0x87, 0xcc, 0xcc, 0x46, 0xf3, 0x38, 0xfa, 0x83, 0xd1, 0x28, 0x4d, 0xea, 0x83, 0xf6, - 0x69, 0x27, 0x7f, 0x1f, 0x7c, 0x2a, 0xeb, 0xd5, 0x83, 0x54, 0xb6, 0x85, 0x13, 0xc2, 0x77, 0x52, - 0xf1, 0xcf, 0x61, 0xfc, 0x20, 0xb3, 0x1a, 0x1f, 0x69, 0x63, 0x4b, 0x77, 0x47, 0x7e, 0x61, 0xaf, - 0x75, 0xc9, 0xb8, 0x83, 0x64, 0x9e, 0x82, 0x97, 0xc9, 0x25, 0x66, 0x56, 0x8b, 0x06, 0xd0, 0x80, - 0xa8, 0xaa, 0x46, 0xd7, 0xf2, 0x28, 0xb3, 0xa9, 0xdd, 0xdc, 0x8a, 0x6e, 0xe1, 0xc9, 0x41, 0xc4, - 0x2e, 0x12, 0x3b, 0x8c, 0xa4, 0xf3, 0xb0, 0x65, 0x18, 0x40, 0x32, 0x2e, 0x31, 0xc3, 0xa4, 0xc2, - 0x95, 0x1e, 0x81, 0x2f, 0x3a, 0x1c, 0xfd, 0xcc, 0x7a, 0x5e, 0x1d, 0x8f, 0x84, 0x9a, 0xe4, 0xdb, - 0xad, 0xdc, 0xad, 0x2c, 0x75, 0x0b, 0xa9, 0x6f, 0xab, 0xa5, 0xa5, 0x1e, 0xad, 0x96, 0x84, 0x55, - 0x61, 0x97, 0x72, 0xa4, 0x0a, 0x3e, 0x85, 0xa3, 0x2d, 0xca, 0xb2, 0x56, 0xb8, 0xc5, 0x5d, 0x65, - 0x5b, 0x30, 0x34, 0xf1, 0x67, 0x30, 0xa9, 0xe4, 0xfd, 0xab, 0xd7, 0xd8, 0xd8, 0x5e, 0x8c, 0x2b, - 0x79, 0x7f, 0x89, 0x0d, 0xff, 0x10, 0x82, 0x75, 0x8a, 0xd9, 0x4a, 0xbb, 0xcc, 0x70, 0x7d, 0x6d, - 0xb8, 0xc4, 0x26, 0xfa, 0x85, 0xc1, 0x78, 0x81, 0xea, 0x01, 0xd5, 0x3b, 0x29, 0x7f, 0xf8, 0x32, - 0x38, 0xff, 0xf2, 0x32, 0xb8, 0x8f, 0xbf, 0x0c, 0x5e, 0xff, 0x32, 0x3c, 0x05, 0x6f, 0xa1, 0x92, - 0x79, 0xac, 0x33, 0x72, 0x84, 0x01, 0xfc, 0x3d, 0x18, 0x9f, 0x25, 0x55, 0xfa, 0x80, 0xf6, 0xb9, - 0xb0, 0x28, 0xfa, 0x89, 0xc1, 0xf8, 0x4a, 0x36, 0x79, 0x5d, 0xbd, 0xa5, 0xb0, 0x29, 0x1c, 0x9d, - 0x15, 0x45, 0x96, 0x26, 0xb2, 0x4a, 0xf3, 0x9d, 0xcd, 0x76, 0x68, 0xa2, 0x1b, 0x2f, 0x06, 0xbd, - 0x33, 0x79, 0x0f, 0x4d, 0xfc, 0x23, 0xf0, 0x2e, 0xf4, 0x42, 0x9b, 0xed, 0x3c, 0xe9, 0xf5, 0x62, - 0xf6, 0x58, 0x3b, 0xa9, 0xc0, 0xb3, 0xba, 0xca, 0xd7, 0x59, 0xbe, 0xd7, 0x95, 0xf8, 0xa2, 0xc3, - 0xd1, 0x9f, 0x0c, 0xdc, 0xff, 0x6a, 0x51, 0x8f, 0x81, 0xa5, 0x76, 0x90, 0x2c, 0xed, 0xd6, 0x76, - 0x32, 0x58, 0xdb, 0x10, 0x26, 0x8d, 0x92, 0xbb, 0x7b, 0x2c, 0x43, 0x7f, 0xea, 0xcc, 0x1c, 0xd1, - 0x42, 0xed, 0xd1, 0x3b, 0x52, 0x86, 0xc1, 0xd4, 0x21, 0x05, 0x5a, 0xd8, 0x69, 0x1e, 0x7a, 0xcd, - 0x47, 0xbf, 0x33, 0xf0, 0x3a, 0xe5, 0x5e, 0x1c, 0x2a, 0xf7, 0xa2, 0x57, 0x6e, 0x7c, 0xde, 0x2a, - 0x37, 0x3e, 0x27, 0x2c, 0xae, 0x5b, 0xe5, 0x8a, 0x6b, 0xea, 0xda, 0x57, 0x2a, 0xaf, 0x8b, 0xf3, - 0xc6, 0xb4, 0x37, 0x10, 0x1d, 0xa6, 0x71, 0x7f, 0xb7, 0x41, 0x65, 0x6b, 0x0e, 0x84, 0x45, 0x24, - 0x8e, 0x2b, 0xbd, 0xd5, 0xa6, 0x4a, 0x03, 0xf8, 0xc7, 0xe0, 0x09, 0xaa, 0x42, 0x97, 0x7a, 0xd0, - 0x20, 0x6d, 0x16, 0xc6, 0x1b, 0x3d, 0xb7, 0xd7, 0x88, 0xe5, 0xb6, 0x28, 0x50, 0x59, 0x4d, 0x1b, - 0xa0, 0xb9, 0xf3, 0x3d, 0x9a, 0xe7, 0xc8, 0x11, 0x06, 0x44, 0xdf, 0x43, 0x70, 0x96, 0xa1, 0xaa, - 0x44, 0x9d, 0xbd, 0xfd, 0x88, 0x71, 0x70, 0xbf, 0x5e, 0x7c, 0xf3, 0xb2, 0xdd, 0x04, 0x3a, 0xf7, - 0xfa, 0x75, 0xfe, 0xa6, 0xdf, 0x4b, 0x59, 0xc8, 0x79, 0xac, 0x07, 0xeb, 0x08, 0x8b, 0xa2, 0x4f, - 0xc1, 0xa5, 0x3d, 0x19, 0x30, 0xbb, 0xff, 0xb4, 0x63, 0xcb, 0xb1, 0xfe, 0xa3, 0x3f, 0xff, 0x2b, - 0x00, 0x00, 0xff, 0xff, 0x0f, 0x40, 0x84, 0xea, 0xe3, 0x07, 0x00, 0x00, + // 952 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x56, 0xcf, 0x8e, 0xe3, 0xc4, + 0x13, 0x56, 0xc7, 0x76, 0x12, 0x57, 0x66, 0xe7, 0xf7, 0x53, 0x6b, 0xc5, 0x9a, 0x45, 0x42, 0xc1, + 0x02, 0x29, 0x20, 0x31, 0xa0, 0x5d, 0x21, 0x21, 0x6e, 0x99, 0x09, 0x5a, 0x85, 0x99, 0x5d, 0x86, + 0xce, 0xcc, 0x70, 0x42, 0xab, 0x4e, 0x52, 0x99, 0x58, 0xeb, 0xc4, 0xa6, 0x6d, 0x4f, 0xe2, 0xb7, + 0xe0, 0x09, 0x90, 0x90, 0x38, 0x71, 0xe0, 0xc0, 0x0b, 0xf0, 0x10, 0xbc, 0x10, 0xaa, 0xee, 0xf6, + 0x9f, 0xb0, 0xb3, 0x68, 0x4f, 0xdc, 0xfa, 0xab, 0xea, 0x7c, 0xe5, 0xfe, 0xea, 0xab, 0x52, 0xe0, + 0x38, 0xda, 0xe6, 0xa8, 0xb6, 0x32, 0x3e, 0x49, 0x55, 0x92, 0x27, 0xbc, 0x5f, 0xe1, 0xf0, 0xf7, + 0x0e, 0x74, 0x67, 0x49, 0xa1, 0x16, 0xc8, 0x8f, 0xa1, 0x33, 0x9d, 0x04, 0x6c, 0xc8, 0x46, 0x8e, + 0xe8, 0x4c, 0x27, 0x9c, 0x83, 0xfb, 0x42, 0x6e, 0x30, 0xe8, 0x0c, 0xd9, 0xc8, 0x17, 0xfa, 0x4c, + 0xb1, 0xab, 0x32, 0xc5, 0xc0, 0x31, 0x31, 0x3a, 0xf3, 0xc7, 0xd0, 0xbf, 0xce, 0x88, 0x6d, 0x83, + 0x81, 0xab, 0xe3, 0x35, 0xa6, 0xdc, 0xa5, 0xcc, 0xb2, 0x5d, 0xa2, 0x96, 0x81, 0x67, 0x72, 0x15, + 0xe6, 0xff, 0x07, 0xe7, 0x5a, 0x5c, 0x04, 0x5d, 0x1d, 0xa6, 0x23, 0x0f, 0xa0, 0x37, 0xc1, 0x95, + 0x2c, 0xe2, 0x3c, 0xe8, 0x0d, 0xd9, 0xa8, 0x2f, 0x2a, 0x48, 0x3c, 0x57, 0x18, 0xe3, 0xad, 0x92, + 0xab, 0xa0, 0x6f, 0x78, 0x2a, 0xcc, 0x4f, 0x80, 0x4f, 0xb7, 0x19, 0x2e, 0x0a, 0x85, 0xb3, 0x57, + 0x51, 0x7a, 0x83, 0x2a, 0x5a, 0x95, 0x81, 0xaf, 0x09, 0xee, 0xc9, 0x50, 0x95, 0xe7, 0x98, 0x4b, + 0xaa, 0x0d, 0x9a, 0xaa, 0x82, 0x3c, 0x84, 0xa3, 0xd9, 0x5a, 0x2a, 0x5c, 0xce, 0x70, 0xa1, 0x30, + 0x0f, 0x06, 0x3a, 0x7d, 0x10, 0x0b, 0x7f, 0x62, 0xe0, 0x4f, 0x64, 0xb6, 0x9e, 0x27, 0x52, 0x2d, + 0xdf, 0x4a, 0xb3, 0x4f, 0xc1, 0x5b, 0x60, 0x1c, 0x67, 0x81, 0x33, 0x74, 0x46, 0x83, 0x27, 0x8f, + 0x4e, 0xea, 0x66, 0xd4, 0x3c, 0x67, 0x18, 0xc7, 0xc2, 0xdc, 0xe2, 0x9f, 0x83, 0x9f, 0xe3, 0x26, + 0x8d, 0x65, 0x8e, 0x59, 0xe0, 0xea, 0x9f, 0xf0, 0xe6, 0x27, 0x57, 0x36, 0x25, 0x9a, 0x4b, 0xe1, + 0x6f, 0x1d, 0x78, 0x70, 0x40, 0xc5, 0x8f, 0x80, 0xed, 0xf5, 0x57, 0x79, 0x82, 0xed, 0x09, 0x95, + 0xfa, 0x8b, 0x3c, 0xc1, 0x4a, 0x42, 0x3b, 0xdd, 0x3f, 0x4f, 0xb0, 0x1d, 0xa1, 0xb5, 0xee, 0x9a, + 0x27, 0xd8, 0x9a, 0x7f, 0x0c, 0xbd, 0x1f, 0x0b, 0x54, 0x11, 0x66, 0x81, 0xa7, 0x2b, 0xff, 0xaf, + 0xa9, 0xfc, 0x5d, 0x81, 0xaa, 0x14, 0x55, 0x9e, 0x5e, 0xaa, 0x3b, 0x6e, 0xda, 0xa7, 0xcf, 0x14, + 0xcb, 0xc9, 0x1d, 0x3d, 0x13, 0xa3, 0xb3, 0x55, 0xc8, 0xf4, 0x8c, 0x14, 0xfa, 0x02, 0x5c, 0xb9, + 0xc7, 0x2c, 0xf0, 0x35, 0xff, 0x07, 0x6f, 0x10, 0xe3, 0x64, 0xbc, 0xc7, 0xec, 0xeb, 0x6d, 0xae, + 0x4a, 0xa1, 0xaf, 0x3f, 0x7e, 0x06, 0x7e, 0x1d, 0x22, 0xe7, 0xbc, 0xc2, 0x52, 0x3f, 0xd0, 0x17, + 0x74, 0xe4, 0x1f, 0x82, 0x77, 0x27, 0xe3, 0xc2, 0x08, 0x3f, 0x78, 0x72, 0xdc, 0xd0, 0x8e, 0xf7, + 0x51, 0x26, 0x4c, 0xf2, 0xab, 0xce, 0x97, 0x2c, 0x7c, 0x1f, 0x5c, 0x0a, 0xf1, 0x77, 0xa0, 0x3b, + 0x4f, 0x8a, 0xed, 0x32, 0x0b, 0xd8, 0xd0, 0x19, 0x39, 0xc2, 0xa2, 0xf0, 0x4f, 0x46, 0x56, 0x33, + 0xd2, 0xb6, 0xda, 0x6b, 0x3e, 0xfe, 0x5d, 0xe8, 0x93, 0xec, 0x2f, 0xef, 0xa4, 0xb2, 0x2d, 0xee, + 0x11, 0xbe, 0x91, 0x8a, 0x7f, 0x06, 0x5d, 0x5d, 0xe4, 0x9e, 0x36, 0x57, 0x74, 0x37, 0x94, 0x17, + 0xf6, 0x5a, 0x2d, 0x96, 0xdb, 0x12, 0xeb, 0x21, 0x78, 0xb1, 0x9c, 0x63, 0x6c, 0x67, 0xc5, 0x00, + 0x32, 0x10, 0xa9, 0x5e, 0x6a, 0xad, 0xef, 0x65, 0x36, 0xbd, 0x31, 0xb7, 0xc2, 0x6b, 0x78, 0x70, + 0x50, 0xb1, 0xae, 0xc4, 0x0e, 0x2b, 0x35, 0x82, 0xf9, 0x56, 0x20, 0x1a, 0xb3, 0x0c, 0x63, 0x5c, + 0xe4, 0xb8, 0xd4, 0x16, 0xe9, 0x8b, 0x1a, 0x87, 0xbf, 0xb0, 0x86, 0x57, 0xd7, 0xa3, 0x41, 0x5a, + 0x24, 0x9b, 0x8d, 0xdc, 0x2e, 0x2d, 0x75, 0x05, 0x49, 0xb7, 0xe5, 0xdc, 0x52, 0x77, 0x96, 0x73, + 0xc2, 0x2a, 0xb5, 0x4b, 0xa3, 0xa3, 0x52, 0x3e, 0x84, 0xc1, 0x06, 0x65, 0x56, 0x28, 0xdc, 0xe0, + 0x36, 0xb7, 0x12, 0xb4, 0x43, 0xfc, 0x11, 0xf4, 0x72, 0x79, 0xfb, 0x92, 0xda, 0x6c, 0xb4, 0xe8, + 0xe6, 0xf2, 0xf6, 0x1c, 0x4b, 0xfe, 0x1e, 0xf8, 0xab, 0x08, 0xe3, 0xa5, 0x4e, 0x19, 0xf3, 0xf5, + 0x75, 0xe0, 0x1c, 0xcb, 0xf0, 0x57, 0x06, 0xdd, 0x19, 0xaa, 0x3b, 0x54, 0x6f, 0x35, 0x99, 0xed, + 0xcd, 0xe5, 0xfc, 0xcb, 0xe6, 0x72, 0xef, 0xdf, 0x5c, 0x5e, 0xb3, 0xb9, 0x1e, 0x82, 0x37, 0x53, + 0x8b, 0xe9, 0x44, 0x7f, 0x91, 0x23, 0x0c, 0x20, 0x8f, 0x8d, 0x17, 0x79, 0x74, 0x87, 0x76, 0x9d, + 0x59, 0x14, 0xfe, 0xcc, 0xa0, 0x7b, 0x21, 0xcb, 0xa4, 0xc8, 0x5f, 0x73, 0xd8, 0x10, 0x06, 0xe3, + 0x34, 0x8d, 0xa3, 0x85, 0xcc, 0xa3, 0x64, 0x6b, 0xbf, 0xb6, 0x1d, 0xa2, 0x1b, 0xcf, 0x5b, 0xda, + 0x99, 0xef, 0x6e, 0x87, 0x68, 0x18, 0xce, 0xf4, 0xc2, 0x31, 0xdb, 0xa3, 0x35, 0x0c, 0x66, 0xcf, + 0xe8, 0x24, 0x3d, 0x70, 0x5c, 0xe4, 0xc9, 0x2a, 0x4e, 0x76, 0xfa, 0x25, 0x7d, 0x51, 0xe3, 0xf0, + 0x2f, 0x06, 0xee, 0x7f, 0xb5, 0x48, 0x8e, 0x80, 0x45, 0xb6, 0x91, 0x2c, 0xaa, 0xd7, 0x4a, 0xaf, + 0xb5, 0x56, 0x02, 0xe8, 0x95, 0x4a, 0x6e, 0x6f, 0x31, 0x0b, 0xfa, 0x7a, 0x56, 0x2b, 0xa8, 0x33, + 0x7a, 0x46, 0xcc, 0x3e, 0xf1, 0x45, 0x05, 0x6b, 0xcf, 0x43, 0xe3, 0xf9, 0xf0, 0x0f, 0x06, 0x5e, + 0xed, 0xdc, 0xb3, 0x43, 0xe7, 0x9e, 0x35, 0xce, 0x9d, 0x9c, 0x56, 0xce, 0x9d, 0x9c, 0x12, 0x16, + 0x97, 0x95, 0x73, 0xc5, 0x25, 0xa9, 0xf6, 0x4c, 0x25, 0x45, 0x7a, 0x5a, 0x1a, 0x79, 0x7d, 0x51, + 0x63, 0x6a, 0xf7, 0xf7, 0x6b, 0x54, 0xf6, 0xcd, 0xbe, 0xb0, 0x88, 0xcc, 0x71, 0xa1, 0xa7, 0xda, + 0xbc, 0xd2, 0x00, 0xfe, 0x11, 0x78, 0x82, 0x5e, 0xa1, 0x9f, 0x7a, 0x20, 0x90, 0x0e, 0x0b, 0x93, + 0x0d, 0x9f, 0xda, 0x6b, 0xc4, 0x72, 0x9d, 0xa6, 0xa8, 0xac, 0xa7, 0x0d, 0xd0, 0xdc, 0xc9, 0x0e, + 0xcd, 0x3a, 0x72, 0x84, 0x01, 0xe1, 0x0f, 0xe0, 0x8f, 0x63, 0x54, 0xb9, 0x28, 0xe2, 0xd7, 0x97, + 0x18, 0x07, 0xf7, 0x9b, 0xd9, 0xb7, 0x2f, 0xaa, 0x49, 0xa0, 0x73, 0xe3, 0x5f, 0xe7, 0x1f, 0xfe, + 0x3d, 0x97, 0xa9, 0x9c, 0x4e, 0x74, 0x63, 0x1d, 0x61, 0x51, 0xf8, 0x09, 0xb8, 0x34, 0x27, 0x2d, + 0x66, 0xf7, 0x4d, 0x33, 0x36, 0xef, 0xea, 0x7f, 0x1c, 0x4f, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, + 0x94, 0xd8, 0xce, 0x85, 0x83, 0x08, 0x00, 0x00, } diff --git a/bolt/internal/internal.proto b/bolt/internal/internal.proto index 2ed54af572..5154a216a8 100644 --- a/bolt/internal/internal.proto +++ b/bolt/internal/internal.proto @@ -23,38 +23,43 @@ message Dashboard { } message DashboardCell { - int32 x = 1; // X-coordinate of Cell in the Dashboard - int32 y = 2; // Y-coordinate of Cell in the Dashboard - int32 w = 3; // Width of Cell in the Dashboard - int32 h = 4; // Height of Cell in the Dashboard - repeated Query queries = 5; // Time-series data queries for Dashboard - string name = 6; // User-facing name for this Dashboard - string type = 7; // Dashboard visualization type - string ID = 8; // id is the unique id of the dashboard. MIGRATED FIELD added in 1.2.0-beta6 + int32 x = 1; // X-coordinate of Cell in the Dashboard + int32 y = 2; // Y-coordinate of Cell in the Dashboard + int32 w = 3; // Width of Cell in the Dashboard + int32 h = 4; // Height of Cell in the Dashboard + repeated Query queries = 5; // Time-series data queries for Dashboard + string name = 6; // User-facing name for this Dashboard + string type = 7; // Dashboard visualization type + string ID = 8; // id is the unique id of the dashboard. MIGRATED FIELD added in 1.2.0-beta6 + map axes = 9; // Axes represent the graphical viewport for a cell's visualizations +} + +message Axis { + repeated int64 bounds = 1; // bounds are an ordered 2-tuple consisting of lower and upper axis extents, respectively } message Template { - string ID = 1; // ID is the unique ID associated with this template - string temp_var = 2; - repeated TemplateValue values = 3; - string type = 4; // Type can be fieldKeys, tagKeys, tagValues, CSV, constant, query, measurements, databases - string label = 5; // Label is a user-facing description of the Template - TemplateQuery query = 6; // Query is used to generate the choices for a template + string ID = 1; // ID is the unique ID associated with this template + string temp_var = 2; + repeated TemplateValue values = 3; + string type = 4; // Type can be fieldKeys, tagKeys, tagValues, CSV, constant, query, measurements, databases + string label = 5; // Label is a user-facing description of the Template + TemplateQuery query = 6; // Query is used to generate the choices for a template } message TemplateValue { - string type = 1; // Type can be tagKey, tagValue, fieldKey, csv, measurement, database, constant - string value = 2; // Value is the specific value used to replace a template in an InfluxQL query - bool selected = 3; // Selected states that this variable has been picked to use for replacement + string type = 1; // Type can be tagKey, tagValue, fieldKey, csv, measurement, database, constant + string value = 2; // Value is the specific value used to replace a template in an InfluxQL query + bool selected = 3; // Selected states that this variable has been picked to use for replacement } message TemplateQuery { - string command = 1; // Command is the query itself - string db = 2; // DB the database for the query (optional) - string rp = 3; // RP is a retention policy and optional; - string measurement = 4; // Measurement is the optinally selected measurement for the query - string tag_key = 5; // TagKey is the optionally selected tag key for the query - string field_key = 6; // FieldKey is the optionally selected field key for the query + string command = 1; // Command is the query itself + string db = 2; // DB the database for the query (optional) + string rp = 3; // RP is a retention policy and optional; + string measurement = 4; // Measurement is the optinally selected measurement for the query + string tag_key = 5; // TagKey is the optionally selected tag key for the query + string field_key = 6; // FieldKey is the optionally selected field key for the query } message Server { @@ -63,54 +68,59 @@ message Server { string Username = 3; // Username is the username to connect to the server string Password = 4; string URL = 5; // URL is the path to the server - int64 SrcID = 6; // SrcID is the ID of the data source + int64 SrcID = 6; // SrcID is the ID of the data source bool Active = 7; // is this the currently active server for the source } message Layout { - string ID = 1; // ID is the unique ID of the layout. - string Application = 2; // Application is the user facing name of this Layout. - string Measurement = 3; // Measurement is the descriptive name of the time series data. - repeated Cell Cells = 4; // Cells are the individual visualization elements. - bool Autoflow = 5; // Autoflow indicates whether the frontend should layout the cells automatically. + string ID = 1; // ID is the unique ID of the layout. + string Application = 2; // Application is the user facing name of this Layout. + string Measurement = 3; // Measurement is the descriptive name of the time series data. + repeated Cell Cells = 4; // Cells are the individual visualization elements. + bool Autoflow = 5; // Autoflow indicates whether the frontend should layout the cells automatically. } message Cell { - int32 x = 1; // X-coordinate of Cell in the Layout - int32 y = 2; // Y-coordinate of Cell in the Layout - int32 w = 3; // Width of Cell in the Layout - int32 h = 4; // Height of Cell in the Layout - repeated Query queries = 5; // Time-series data queries for Cell. - string i = 6; // Unique identifier for the cell - string name = 7; // User-facing name for this cell - repeated int64 yranges = 8; // Limits of the y-axes - repeated string ylabels = 9; // Labels of the y-axes - string type = 10; // Cell visualization type + int32 x = 1; // X-coordinate of Cell in the Layout + int32 y = 2; // Y-coordinate of Cell in the Layout + int32 w = 3; // Width of Cell in the Layout + int32 h = 4; // Height of Cell in the Layout + repeated Query queries = 5; // Time-series data queries for Cell. + string i = 6; // Unique identifier for the cell + string name = 7; // User-facing name for this cell + repeated int64 yranges = 8; // Limits of the y-axes + repeated string ylabels = 9; // Labels of the y-axes + string type = 10; // Cell visualization type } message Query { - string Command = 1; // Command is the query itself - string DB = 2; // DB the database for the query (optional) - string RP = 3; // RP is a retention policy and optional; - repeated string GroupBys= 4; // GroupBys define the groups to combine in the query - repeated string Wheres = 5; // Wheres define the restrictions on the query - string Label = 6; // Label is the name of the Y-Axis - Range Range = 7; // Range is the upper and lower bound of the Y-Axis + string Command = 1; // Command is the query itself + string DB = 2; // DB the database for the query (optional) + string RP = 3; // RP is a retention policy and optional; + repeated string GroupBys= 4; // GroupBys define the groups to combine in the query + repeated string Wheres = 5; // Wheres define the restrictions on the query + string Label = 6; // Label is the name of the Y-Axis + Range Range = 7; // Range is the upper and lower bound of the Y-Axis } message Range { - int64 Upper = 1; // Upper is the upper-bound of the range - int64 Lower = 2; // Lower is the lower-bound of the range + int64 Upper = 1; // Upper is the upper-bound of the range + int64 Lower = 2; // Lower is the lower-bound of the range } message AlertRule { - string ID = 1; // ID is the unique ID of this alert rule - string JSON = 2; // JSON byte representation of the alert - int64 SrcID = 3; // SrcID is the id of the source this alert is associated with - int64 KapaID = 4; // KapaID is the id of the kapacitor this alert is associated with + string ID = 1; // ID is the unique ID of this alert rule + string JSON = 2; // JSON byte representation of the alert + int64 SrcID = 3; // SrcID is the id of the source this alert is associated with + int64 KapaID = 4; // KapaID is the id of the kapacitor this alert is associated with } message User { - uint64 ID = 1; // ID is the unique ID of this user - string Name = 2; // Name is the user's login name + uint64 ID = 1; // ID is the unique ID of this user + string Name = 2; // Name is the user's login name } + +// The following is a vim modeline, it autoconfigures vim to have the +// appropriate tabbing and whitespace management to edit this file +// +// vim: ai:ts=4:noet:sts=4 diff --git a/bolt/internal/internal_test.go b/bolt/internal/internal_test.go index 2d6966036c..cbfa2d459a 100644 --- a/bolt/internal/internal_test.go +++ b/bolt/internal/internal_test.go @@ -4,6 +4,7 @@ import ( "reflect" "testing" + "github.com/google/go-cmp/cmp" "github.com/influxdata/chronograf" "github.com/influxdata/chronograf/bolt/internal" ) @@ -136,3 +137,45 @@ func TestMarshalLayout(t *testing.T) { t.Fatalf("source protobuf copy error: got %#v, expected %#v", vv, layout) } } + +func Test_MarshalDashboard(t *testing.T) { + dashboard := chronograf.Dashboard{ + ID: 1, + Cells: []chronograf.DashboardCell{ + { + ID: "9b5367de-c552-4322-a9e8-7f384cbd235c", + X: 0, + Y: 0, + W: 4, + H: 4, + Name: "Super awesome query", + Queries: []chronograf.DashboardQuery{ + { + Command: "select * from cpu", + Label: "CPU Utilization", + Range: &chronograf.Range{ + Upper: int64(100), + }, + }, + }, + Axes: map[string]chronograf.Axis{ + "y": chronograf.Axis{ + Bounds: [2]int64{0, 100}, + }, + }, + Type: "line", + }, + }, + Templates: []chronograf.Template{}, + Name: "Dashboard", + } + + var actual chronograf.Dashboard + if buf, err := internal.MarshalDashboard(dashboard); err != nil { + t.Fatal("Error marshaling dashboard: err", err) + } else if err := internal.UnmarshalDashboard(buf, &actual); err != nil { + t.Fatal("Error unmarshaling dashboard: err:", err) + } else if !cmp.Equal(dashboard, actual) { + t.Fatalf("Dashboard protobuf copy error: diff follows:\n%s", cmp.Diff(dashboard, actual)) + } +} diff --git a/chronograf.go b/chronograf.go index 868b0aa412..4bf273910c 100644 --- a/chronograf.go +++ b/chronograf.go @@ -29,6 +29,7 @@ const ( ErrAlertNotFound = Error("alert not found") ErrAuthentication = Error("user not authenticated") ErrUninitialized = Error("client uninitialized. Call Open() method") + ErrInvalidAxis = Error("Unexpected axis in cell. Valid axes are 'x', 'y', and 'y2'") ) // Error is a domain error encountered while processing chronograf requests @@ -566,6 +567,11 @@ type Dashboard struct { Name string `json:"name"` } +// Axis represents the visible extents of a visualization +type Axis struct { + Bounds [2]int64 `json:"bounds"` // bounds are an ordered 2-tuple consisting of lower and upper axis extents, respectively +} + // DashboardCell holds visual and query information for a cell type DashboardCell struct { ID string `json:"i"` @@ -575,6 +581,7 @@ type DashboardCell struct { H int32 `json:"h"` Name string `json:"name"` Queries []DashboardQuery `json:"queries"` + Axes map[string]Axis `json:"axes"` Type string `json:"type"` } diff --git a/server/cells.go b/server/cells.go index b6a79290b6..f60437c910 100644 --- a/server/cells.go +++ b/server/cells.go @@ -43,9 +43,23 @@ func newCellResponses(dID chronograf.DashboardID, dcells []chronograf.DashboardC return cells } -// ValidDashboardCellRequest verifies that the dashboard cells have a query +// ValidDashboardCellRequest verifies that the dashboard cells have a query and +// have the correct axes specified func ValidDashboardCellRequest(c *chronograf.DashboardCell) error { CorrectWidthHeight(c) + return HasCorrectAxes(c) +} + +// HasCorrectAxes verifies that only permitted axes exist within a DashboardCell +func HasCorrectAxes(c *chronograf.DashboardCell) error { + for axis, _ := range c.Axes { + switch axis { + case "x", "y", "y2": + // no-op + default: + return chronograf.ErrInvalidAxis + } + } return nil } diff --git a/server/cells_test.go b/server/cells_test.go new file mode 100644 index 0000000000..be694b3dff --- /dev/null +++ b/server/cells_test.go @@ -0,0 +1,60 @@ +package server_test + +import ( + "testing" + + "github.com/influxdata/chronograf" + "github.com/influxdata/chronograf/server" +) + +func Test_Cells_CorrectAxis(t *testing.T) { + t.Parallel() + + axisTests := []struct { + name string + cell *chronograf.DashboardCell + shouldFail bool + }{ + { + "correct axes", + &chronograf.DashboardCell{ + Axes: map[string]chronograf.Axis{ + "x": chronograf.Axis{ + Bounds: [2]int64{0, 100}, + }, + "y": chronograf.Axis{ + Bounds: [2]int64{0, 100}, + }, + "y2": chronograf.Axis{ + Bounds: [2]int64{0, 100}, + }, + }, + }, + false, + }, + { + "invalid axes present", + &chronograf.DashboardCell{ + Axes: map[string]chronograf.Axis{ + "axis of evil": chronograf.Axis{ + Bounds: [2]int64{666, 666}, + }, + "axis of awesome": chronograf.Axis{ + Bounds: [2]int64{1337, 31337}, + }, + }, + }, + true, + }, + } + + for _, test := range axisTests { + t.Run(test.name, func(tt *testing.T) { + if err := server.HasCorrectAxes(test.cell); err != nil && !test.shouldFail { + t.Errorf("%q: Unexpected error: err: %s", test.name, err) + } else if err == nil && test.shouldFail { + t.Errorf("%q: Expected error and received none", test.name) + } + }) + } +} diff --git a/server/dashboards_test.go b/server/dashboards_test.go index 613d56d574..b5116913c5 100644 --- a/server/dashboards_test.go +++ b/server/dashboards_test.go @@ -4,6 +4,7 @@ import ( "reflect" "testing" + "github.com/google/go-cmp/cmp" "github.com/influxdata/chronograf" ) @@ -219,6 +220,14 @@ func Test_newDashboardResponse(t *testing.T) { Command: "SELECT donors from hill_valley_preservation_society where time > '1985-10-25 08:00:00'", }, }, + Axes: map[string]chronograf.Axis{ + "x": chronograf.Axis{ + Bounds: [2]int64{0, 100}, + }, + "y": chronograf.Axis{ + Bounds: [2]int64{2, 95}, + }, + }, }, { ID: "b", @@ -257,6 +266,14 @@ func Test_newDashboardResponse(t *testing.T) { }, }, }, + Axes: map[string]chronograf.Axis{ + "x": chronograf.Axis{ + Bounds: [2]int64{0, 100}, + }, + "y": chronograf.Axis{ + Bounds: [2]int64{2, 95}, + }, + }, }, }, dashboardCellResponse{ @@ -301,8 +318,8 @@ func Test_newDashboardResponse(t *testing.T) { }, } for _, tt := range tests { - if got := newDashboardResponse(tt.d); !reflect.DeepEqual(got, tt.want) { - t.Errorf("%q. newDashboardResponse() = \n%#v\n\n, want\n\n%#v", tt.name, got, tt.want) + if got := newDashboardResponse(tt.d); !cmp.Equal(got, tt.want) { + t.Errorf("%q. newDashboardResponse() = diff:\n%s", tt.name, cmp.Diff(got, tt.want)) } } } diff --git a/server/swagger.json b/server/swagger.json index 058be7dadf..486984cae5 100644 --- a/server/swagger.json +++ b/server/swagger.json @@ -2714,7 +2714,6 @@ "hipchat", "opsgenie", "pagerduty", - "pushover", "victorops", "smtp", "email", @@ -3716,6 +3715,21 @@ "$ref": "#/definitions/DashboardQuery" } }, + "axes": { + "description": "The viewport for a cell's visualizations", + "type": "object", + "properties": { + "x": { + "$ref": "#/definitions/DashboardRange" + }, + "y": { + "$ref": "#/definitions/DashboardRange" + }, + "y2": { + "$ref": "#/definitions/DashboardRange" + } + } + }, "type": { "description": "Cell visualization type", "type": "string", @@ -3797,6 +3811,22 @@ } } }, + "DashboardRange": { + "type": "object", + "description": "A description of a particular axis for a visualization", + "properties": { + "bounds": { + "type": "array", + "minItems": 0, + "maxItems": 2, + "description": "The extents of an axis in the form [lower, upper]. Clients determine whether bounds are to be inclusive or exclusive of their limits", + "items": { + "type": "integer", + "format": "int64" + } + } + } + }, "Routes": { "type": "object", "properties": {