Merge branch 'master' of github.com:influxdata/chronograf
commit
4d498eba75
|
@ -6,6 +6,7 @@
|
|||
1. [#3559](https://github.com/influxdata/chronograf/pull/3559): Add ability to export and import dashboards
|
||||
1. [#3556](https://github.com/influxdata/chronograf/pull/3556): Add ability to override template variables and time ranges via URL query
|
||||
1. [#3814](https://github.com/influxdata/chronograf/pull/3814): Add pprof routes to chronograf server
|
||||
1. [#3806](https://github.com/influxdata/chronograf/pull/3806): Add API to get/update Log Viewer UI config
|
||||
|
||||
### UI Improvements
|
||||
|
||||
|
|
|
@ -33,15 +33,16 @@ type Client struct {
|
|||
Now func() time.Time
|
||||
LayoutIDs chronograf.ID
|
||||
|
||||
BuildStore *BuildStore
|
||||
SourcesStore *SourcesStore
|
||||
ServersStore *ServersStore
|
||||
LayoutsStore *LayoutsStore
|
||||
DashboardsStore *DashboardsStore
|
||||
UsersStore *UsersStore
|
||||
OrganizationsStore *OrganizationsStore
|
||||
ConfigStore *ConfigStore
|
||||
MappingsStore *MappingsStore
|
||||
BuildStore *BuildStore
|
||||
SourcesStore *SourcesStore
|
||||
ServersStore *ServersStore
|
||||
LayoutsStore *LayoutsStore
|
||||
DashboardsStore *DashboardsStore
|
||||
UsersStore *UsersStore
|
||||
OrganizationsStore *OrganizationsStore
|
||||
ConfigStore *ConfigStore
|
||||
MappingsStore *MappingsStore
|
||||
OrganizationConfigStore *OrganizationConfigStore
|
||||
}
|
||||
|
||||
// NewClient initializes all stores
|
||||
|
@ -62,6 +63,7 @@ func NewClient() *Client {
|
|||
c.OrganizationsStore = &OrganizationsStore{client: c}
|
||||
c.ConfigStore = &ConfigStore{client: c}
|
||||
c.MappingsStore = &MappingsStore{client: c}
|
||||
c.OrganizationConfigStore = &OrganizationConfigStore{client: c}
|
||||
return c
|
||||
}
|
||||
|
||||
|
@ -161,6 +163,10 @@ func (c *Client) initialize(ctx context.Context) error {
|
|||
if _, err := tx.CreateBucketIfNotExists(MappingsBucket); err != nil {
|
||||
return err
|
||||
}
|
||||
// Always create OrganizationConfig bucket.
|
||||
if _, err := tx.CreateBucketIfNotExists(OrganizationConfigBucket); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
|
@ -197,6 +203,9 @@ func (c *Client) migrate(ctx context.Context, build chronograf.BuildInfo) error
|
|||
if err := c.MappingsStore.Migrate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.OrganizationConfigStore.Migrate(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
MigrateAll(c)
|
||||
}
|
||||
|
|
|
@ -747,6 +747,81 @@ func UnmarshalConfigPB(data []byte, c *Config) error {
|
|||
return proto.Unmarshal(data, c)
|
||||
}
|
||||
|
||||
// MarshalOrganizationConfig encodes a config to binary protobuf format.
|
||||
func MarshalOrganizationConfig(c *chronograf.OrganizationConfig) ([]byte, error) {
|
||||
columns := make([]*LogViewerColumn, len(c.LogViewer.Columns))
|
||||
|
||||
for i, column := range c.LogViewer.Columns {
|
||||
encodings := make([]*ColumnEncoding, len(column.Encodings))
|
||||
|
||||
for j, e := range column.Encodings {
|
||||
encodings[j] = &ColumnEncoding{
|
||||
Type: e.Type,
|
||||
Value: e.Value,
|
||||
Name: e.Name,
|
||||
}
|
||||
}
|
||||
|
||||
columns[i] = &LogViewerColumn{
|
||||
Name: column.Name,
|
||||
Position: column.Position,
|
||||
Encodings: encodings,
|
||||
}
|
||||
}
|
||||
|
||||
return MarshalOrganizationConfigPB(&OrganizationConfig{
|
||||
OrganizationID: c.OrganizationID,
|
||||
LogViewer: &LogViewerConfig{
|
||||
Columns: columns,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// MarshalOrganizationConfigPB encodes a config to binary protobuf format.
|
||||
func MarshalOrganizationConfigPB(c *OrganizationConfig) ([]byte, error) {
|
||||
return proto.Marshal(c)
|
||||
}
|
||||
|
||||
// UnmarshalOrganizationConfig decodes a config from binary protobuf data.
|
||||
func UnmarshalOrganizationConfig(data []byte, c *chronograf.OrganizationConfig) error {
|
||||
var pb OrganizationConfig
|
||||
|
||||
if err := UnmarshalOrganizationConfigPB(data, &pb); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if pb.LogViewer == nil {
|
||||
return fmt.Errorf("Log Viewer config is nil")
|
||||
}
|
||||
|
||||
c.OrganizationID = pb.OrganizationID
|
||||
|
||||
columns := make([]chronograf.LogViewerColumn, len(pb.LogViewer.Columns))
|
||||
|
||||
for i, c := range pb.LogViewer.Columns {
|
||||
columns[i].Name = c.Name
|
||||
columns[i].Position = c.Position
|
||||
|
||||
encodings := make([]chronograf.ColumnEncoding, len(c.Encodings))
|
||||
for j, e := range c.Encodings {
|
||||
encodings[j].Type = e.Type
|
||||
encodings[j].Value = e.Value
|
||||
encodings[j].Name = e.Name
|
||||
}
|
||||
|
||||
columns[i].Encodings = encodings
|
||||
}
|
||||
|
||||
c.LogViewer.Columns = columns
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalOrganizationConfigPB decodes a config from binary protobuf data.
|
||||
func UnmarshalOrganizationConfigPB(data []byte, c *OrganizationConfig) error {
|
||||
return proto.Unmarshal(data, c)
|
||||
}
|
||||
|
||||
// MarshalMapping encodes a mapping to binary protobuf format.
|
||||
func MarshalMapping(m *chronograf.Mapping) ([]byte, error) {
|
||||
|
||||
|
|
|
@ -33,6 +33,10 @@ It has these top-level messages:
|
|||
Organization
|
||||
Config
|
||||
AuthConfig
|
||||
OrganizationConfig
|
||||
LogViewerConfig
|
||||
LogViewerColumn
|
||||
ColumnEncoding
|
||||
BuildInfo
|
||||
*/
|
||||
package internal
|
||||
|
@ -1340,6 +1344,110 @@ func (m *AuthConfig) GetSuperAdminNewUsers() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
type OrganizationConfig struct {
|
||||
OrganizationID string `protobuf:"bytes,1,opt,name=OrganizationID,proto3" json:"OrganizationID,omitempty"`
|
||||
LogViewer *LogViewerConfig `protobuf:"bytes,2,opt,name=LogViewer" json:"LogViewer,omitempty"`
|
||||
}
|
||||
|
||||
func (m *OrganizationConfig) Reset() { *m = OrganizationConfig{} }
|
||||
func (m *OrganizationConfig) String() string { return proto.CompactTextString(m) }
|
||||
func (*OrganizationConfig) ProtoMessage() {}
|
||||
func (*OrganizationConfig) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{25} }
|
||||
|
||||
func (m *OrganizationConfig) GetOrganizationID() string {
|
||||
if m != nil {
|
||||
return m.OrganizationID
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *OrganizationConfig) GetLogViewer() *LogViewerConfig {
|
||||
if m != nil {
|
||||
return m.LogViewer
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type LogViewerConfig struct {
|
||||
Columns []*LogViewerColumn `protobuf:"bytes,1,rep,name=Columns" json:"Columns,omitempty"`
|
||||
}
|
||||
|
||||
func (m *LogViewerConfig) Reset() { *m = LogViewerConfig{} }
|
||||
func (m *LogViewerConfig) String() string { return proto.CompactTextString(m) }
|
||||
func (*LogViewerConfig) ProtoMessage() {}
|
||||
func (*LogViewerConfig) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{26} }
|
||||
|
||||
func (m *LogViewerConfig) GetColumns() []*LogViewerColumn {
|
||||
if m != nil {
|
||||
return m.Columns
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type LogViewerColumn struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"`
|
||||
Position int32 `protobuf:"varint,2,opt,name=Position,proto3" json:"Position,omitempty"`
|
||||
Encodings []*ColumnEncoding `protobuf:"bytes,3,rep,name=Encodings" json:"Encodings,omitempty"`
|
||||
}
|
||||
|
||||
func (m *LogViewerColumn) Reset() { *m = LogViewerColumn{} }
|
||||
func (m *LogViewerColumn) String() string { return proto.CompactTextString(m) }
|
||||
func (*LogViewerColumn) ProtoMessage() {}
|
||||
func (*LogViewerColumn) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{27} }
|
||||
|
||||
func (m *LogViewerColumn) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *LogViewerColumn) GetPosition() int32 {
|
||||
if m != nil {
|
||||
return m.Position
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *LogViewerColumn) GetEncodings() []*ColumnEncoding {
|
||||
if m != nil {
|
||||
return m.Encodings
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ColumnEncoding struct {
|
||||
Type string `protobuf:"bytes,1,opt,name=Type,proto3" json:"Type,omitempty"`
|
||||
Value string `protobuf:"bytes,2,opt,name=Value,proto3" json:"Value,omitempty"`
|
||||
Name string `protobuf:"bytes,3,opt,name=Name,proto3" json:"Name,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ColumnEncoding) Reset() { *m = ColumnEncoding{} }
|
||||
func (m *ColumnEncoding) String() string { return proto.CompactTextString(m) }
|
||||
func (*ColumnEncoding) ProtoMessage() {}
|
||||
func (*ColumnEncoding) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{28} }
|
||||
|
||||
func (m *ColumnEncoding) GetType() string {
|
||||
if m != nil {
|
||||
return m.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ColumnEncoding) GetValue() string {
|
||||
if m != nil {
|
||||
return m.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ColumnEncoding) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type BuildInfo struct {
|
||||
Version string `protobuf:"bytes,1,opt,name=Version,proto3" json:"Version,omitempty"`
|
||||
Commit string `protobuf:"bytes,2,opt,name=Commit,proto3" json:"Commit,omitempty"`
|
||||
|
@ -1348,7 +1456,7 @@ type BuildInfo struct {
|
|||
func (m *BuildInfo) Reset() { *m = BuildInfo{} }
|
||||
func (m *BuildInfo) String() string { return proto.CompactTextString(m) }
|
||||
func (*BuildInfo) ProtoMessage() {}
|
||||
func (*BuildInfo) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{25} }
|
||||
func (*BuildInfo) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{29} }
|
||||
|
||||
func (m *BuildInfo) GetVersion() string {
|
||||
if m != nil {
|
||||
|
@ -1390,117 +1498,128 @@ func init() {
|
|||
proto.RegisterType((*Organization)(nil), "internal.Organization")
|
||||
proto.RegisterType((*Config)(nil), "internal.Config")
|
||||
proto.RegisterType((*AuthConfig)(nil), "internal.AuthConfig")
|
||||
proto.RegisterType((*OrganizationConfig)(nil), "internal.OrganizationConfig")
|
||||
proto.RegisterType((*LogViewerConfig)(nil), "internal.LogViewerConfig")
|
||||
proto.RegisterType((*LogViewerColumn)(nil), "internal.LogViewerColumn")
|
||||
proto.RegisterType((*ColumnEncoding)(nil), "internal.ColumnEncoding")
|
||||
proto.RegisterType((*BuildInfo)(nil), "internal.BuildInfo")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("internal.proto", fileDescriptorInternal) }
|
||||
|
||||
var fileDescriptorInternal = []byte{
|
||||
// 1691 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xdd, 0x8f, 0xe3, 0x48,
|
||||
0x11, 0x97, 0x13, 0x3b, 0x89, 0x2b, 0x99, 0xb9, 0x91, 0x59, 0xdd, 0x99, 0x03, 0xa1, 0x60, 0xf1,
|
||||
0x31, 0x7c, 0xdc, 0x72, 0x9a, 0x13, 0x12, 0x3a, 0xdd, 0x9d, 0x34, 0x1f, 0xb7, 0xcb, 0xec, 0xe7,
|
||||
0x6c, 0x67, 0x76, 0x78, 0x42, 0xa7, 0x4e, 0xdc, 0x49, 0x5a, 0xe7, 0xd8, 0xa6, 0xdd, 0x9e, 0x19,
|
||||
0xf3, 0xcc, 0xdf, 0x81, 0x84, 0x04, 0xef, 0x08, 0xf1, 0x88, 0xc4, 0x3b, 0x7f, 0x00, 0xff, 0x0a,
|
||||
0xaf, 0xa8, 0xfa, 0xc3, 0x69, 0xcf, 0x64, 0x57, 0x8b, 0x84, 0xee, 0xad, 0x7f, 0x55, 0x95, 0xea,
|
||||
0xea, 0xea, 0xaa, 0x5f, 0x97, 0x03, 0xfb, 0x3c, 0x97, 0x4c, 0xe4, 0x34, 0x7b, 0x58, 0x8a, 0x42,
|
||||
0x16, 0xd1, 0xc8, 0xe2, 0xe4, 0x0f, 0x7d, 0x18, 0xcc, 0x8a, 0x5a, 0x2c, 0x58, 0xb4, 0x0f, 0xbd,
|
||||
0xf3, 0xb3, 0xd8, 0x9b, 0x7a, 0x87, 0x7d, 0xd2, 0x3b, 0x3f, 0x8b, 0x22, 0xf0, 0x5f, 0xd0, 0x0d,
|
||||
0x8b, 0x7b, 0x53, 0xef, 0x30, 0x24, 0x6a, 0x8d, 0xb2, 0xcb, 0xa6, 0x64, 0x71, 0x5f, 0xcb, 0x70,
|
||||
0x1d, 0x7d, 0x08, 0xa3, 0xd7, 0x15, 0x7a, 0xdb, 0xb0, 0xd8, 0x57, 0xf2, 0x16, 0xa3, 0xee, 0x82,
|
||||
0x56, 0xd5, 0x4d, 0x21, 0xd2, 0x38, 0xd0, 0x3a, 0x8b, 0xa3, 0x03, 0xe8, 0xbf, 0x26, 0xcf, 0xe2,
|
||||
0x81, 0x12, 0xe3, 0x32, 0x8a, 0x61, 0x78, 0xc6, 0x96, 0xb4, 0xce, 0x64, 0x3c, 0x9c, 0x7a, 0x87,
|
||||
0x23, 0x62, 0x21, 0xfa, 0xb9, 0x64, 0x19, 0x5b, 0x09, 0xba, 0x8c, 0x47, 0xda, 0x8f, 0xc5, 0xd1,
|
||||
0x43, 0x88, 0xce, 0xf3, 0x8a, 0x2d, 0x6a, 0xc1, 0x66, 0x5f, 0xf3, 0xf2, 0x8a, 0x09, 0xbe, 0x6c,
|
||||
0xe2, 0x50, 0x39, 0xd8, 0xa1, 0xc1, 0x5d, 0x9e, 0x33, 0x49, 0x71, 0x6f, 0x50, 0xae, 0x2c, 0x8c,
|
||||
0x12, 0x98, 0xcc, 0xd6, 0x54, 0xb0, 0x74, 0xc6, 0x16, 0x82, 0xc9, 0x78, 0xac, 0xd4, 0x1d, 0x19,
|
||||
0xda, 0xbc, 0x14, 0x2b, 0x9a, 0xf3, 0xdf, 0x53, 0xc9, 0x8b, 0x3c, 0x9e, 0x68, 0x1b, 0x57, 0x86,
|
||||
0x59, 0x22, 0x45, 0xc6, 0xe2, 0x3d, 0x9d, 0x25, 0x5c, 0x47, 0xdf, 0x85, 0xd0, 0x1c, 0x86, 0x5c,
|
||||
0xc4, 0xfb, 0x4a, 0xb1, 0x15, 0x24, 0x7f, 0xf7, 0x20, 0x3c, 0xa3, 0xd5, 0x7a, 0x5e, 0x50, 0x91,
|
||||
0xbe, 0xd3, 0x4d, 0x7c, 0x04, 0xc1, 0x82, 0x65, 0x59, 0x15, 0xf7, 0xa7, 0xfd, 0xc3, 0xf1, 0xd1,
|
||||
0x07, 0x0f, 0xdb, 0x2b, 0x6e, 0xfd, 0x9c, 0xb2, 0x2c, 0x23, 0xda, 0x2a, 0xfa, 0x18, 0x42, 0xc9,
|
||||
0x36, 0x65, 0x46, 0x25, 0xab, 0x62, 0x5f, 0xfd, 0x24, 0xda, 0xfe, 0xe4, 0xd2, 0xa8, 0xc8, 0xd6,
|
||||
0xe8, 0xde, 0x41, 0x83, 0xfb, 0x07, 0x4d, 0xfe, 0xed, 0xc3, 0x5e, 0x67, 0xbb, 0x68, 0x02, 0xde,
|
||||
0xad, 0x8a, 0x3c, 0x20, 0xde, 0x2d, 0xa2, 0x46, 0x45, 0x1d, 0x10, 0xaf, 0x41, 0x74, 0xa3, 0x2a,
|
||||
0x27, 0x20, 0xde, 0x0d, 0xa2, 0xb5, 0xaa, 0x97, 0x80, 0x78, 0xeb, 0xe8, 0x27, 0x30, 0xfc, 0x5d,
|
||||
0xcd, 0x04, 0x67, 0x55, 0x1c, 0xa8, 0xe8, 0xde, 0xdb, 0x46, 0xf7, 0xaa, 0x66, 0xa2, 0x21, 0x56,
|
||||
0x8f, 0xd9, 0x50, 0xb5, 0xa6, 0x0b, 0x47, 0xad, 0x51, 0x26, 0xb1, 0x2e, 0x87, 0x5a, 0x86, 0x6b,
|
||||
0x93, 0x45, 0x5d, 0x2d, 0x98, 0xc5, 0x5f, 0x82, 0x4f, 0x6f, 0x59, 0x15, 0x87, 0xca, 0xff, 0xf7,
|
||||
0xdf, 0x90, 0xb0, 0x87, 0xc7, 0xb7, 0xac, 0xfa, 0x32, 0x97, 0xa2, 0x21, 0xca, 0x3c, 0xfa, 0x31,
|
||||
0x0c, 0x16, 0x45, 0x56, 0x88, 0x2a, 0x86, 0xbb, 0x81, 0x9d, 0xa2, 0x9c, 0x18, 0x75, 0x74, 0x08,
|
||||
0x83, 0x8c, 0xad, 0x58, 0x9e, 0xaa, 0xba, 0x19, 0x1f, 0x1d, 0x6c, 0x0d, 0x9f, 0x29, 0x39, 0x31,
|
||||
0xfa, 0xe8, 0x53, 0x98, 0x48, 0x3a, 0xcf, 0xd8, 0xcb, 0x12, 0xb3, 0x58, 0xa9, 0x1a, 0x1a, 0x1f,
|
||||
0xbd, 0xef, 0xdc, 0x87, 0xa3, 0x25, 0x1d, 0xdb, 0xe8, 0x33, 0x98, 0x2c, 0x39, 0xcb, 0x52, 0xfb,
|
||||
0xdb, 0x3d, 0x15, 0x54, 0xbc, 0xfd, 0x2d, 0x61, 0x39, 0xdd, 0xe0, 0x2f, 0x1e, 0xa1, 0x19, 0xe9,
|
||||
0x58, 0x47, 0xdf, 0x03, 0x90, 0x7c, 0xc3, 0x1e, 0x15, 0x62, 0x43, 0xa5, 0x29, 0x43, 0x47, 0x12,
|
||||
0x7d, 0x0e, 0x7b, 0x29, 0x5b, 0xf0, 0x0d, 0xcd, 0x2e, 0x32, 0xba, 0x60, 0x55, 0xfc, 0x9e, 0x0a,
|
||||
0xcd, 0xad, 0x2e, 0x57, 0x4d, 0xba, 0xd6, 0x1f, 0x3e, 0x86, 0xb0, 0x4d, 0x1f, 0xf6, 0xf7, 0xd7,
|
||||
0xac, 0x51, 0xc5, 0x10, 0x12, 0x5c, 0x46, 0x3f, 0x80, 0xe0, 0x9a, 0x66, 0xb5, 0x2e, 0xe4, 0xf1,
|
||||
0xd1, 0xfe, 0xd6, 0xeb, 0xf1, 0x2d, 0xaf, 0x88, 0x56, 0x7e, 0xda, 0xfb, 0x95, 0x97, 0x3c, 0x86,
|
||||
0xbd, 0xce, 0x46, 0x18, 0x38, 0xaf, 0xbe, 0xcc, 0x97, 0x85, 0x58, 0xb0, 0x54, 0xf9, 0x1c, 0x11,
|
||||
0x47, 0x12, 0xbd, 0x0f, 0x83, 0x94, 0xaf, 0xb8, 0xac, 0x4c, 0xb9, 0x19, 0x94, 0xfc, 0xc3, 0x83,
|
||||
0x89, 0x9b, 0xcd, 0xe8, 0xa7, 0x70, 0x70, 0xcd, 0x84, 0xe4, 0x0b, 0x9a, 0x5d, 0xf2, 0x0d, 0xc3,
|
||||
0x8d, 0xd5, 0x4f, 0x46, 0xe4, 0x9e, 0x3c, 0xfa, 0x18, 0x06, 0x55, 0x21, 0xe4, 0x49, 0xa3, 0xaa,
|
||||
0xf6, 0x6d, 0x59, 0x36, 0x76, 0xc8, 0x53, 0x37, 0x82, 0x96, 0x25, 0xcf, 0x57, 0x96, 0x0b, 0x2d,
|
||||
0x8e, 0x7e, 0x04, 0xfb, 0x4b, 0x7e, 0xfb, 0x88, 0x8b, 0x4a, 0x9e, 0x16, 0x59, 0xbd, 0xc9, 0x55,
|
||||
0x05, 0x8f, 0xc8, 0x1d, 0xe9, 0x13, 0x7f, 0xe4, 0x1d, 0xf4, 0x9e, 0xf8, 0xa3, 0xe0, 0x60, 0x90,
|
||||
0x94, 0xb0, 0xdf, 0xdd, 0x09, 0xdb, 0xd2, 0x06, 0xa1, 0x38, 0x41, 0xa7, 0xb7, 0x23, 0x8b, 0xa6,
|
||||
0x30, 0x4e, 0x79, 0x55, 0x66, 0xb4, 0x71, 0x68, 0xc3, 0x15, 0x21, 0x07, 0x5e, 0xf3, 0x8a, 0xcf,
|
||||
0x33, 0x4d, 0xe5, 0x23, 0x62, 0x61, 0xb2, 0x82, 0x40, 0x95, 0xb5, 0x43, 0x42, 0xa1, 0x25, 0x21,
|
||||
0x45, 0xfd, 0x3d, 0x87, 0xfa, 0x0f, 0xa0, 0xff, 0x6b, 0x76, 0x6b, 0x5e, 0x03, 0x5c, 0xb6, 0x54,
|
||||
0xe5, 0x3b, 0x54, 0xf5, 0x00, 0x82, 0x2b, 0x75, 0xed, 0x9a, 0x42, 0x34, 0x48, 0xbe, 0x80, 0x81,
|
||||
0x6e, 0x8b, 0xd6, 0xb3, 0xe7, 0x78, 0x9e, 0xc2, 0xf8, 0xa5, 0xe0, 0x2c, 0x97, 0x9a, 0x7c, 0xcc,
|
||||
0x11, 0x1c, 0x51, 0xf2, 0x37, 0x0f, 0x7c, 0x75, 0x4b, 0x09, 0x4c, 0x32, 0xb6, 0xa2, 0x8b, 0xe6,
|
||||
0xa4, 0xa8, 0xf3, 0xb4, 0x8a, 0xbd, 0x69, 0xff, 0xb0, 0x4f, 0x3a, 0x32, 0x2c, 0x8f, 0xb9, 0xd6,
|
||||
0xf6, 0xa6, 0xfd, 0xc3, 0x90, 0x18, 0x84, 0xa1, 0x65, 0x74, 0xce, 0x32, 0x73, 0x04, 0x0d, 0xd0,
|
||||
0xba, 0x14, 0x6c, 0xc9, 0x6f, 0xcd, 0x31, 0x0c, 0x42, 0x79, 0x55, 0x2f, 0x51, 0xae, 0x4f, 0x62,
|
||||
0x10, 0x1e, 0x60, 0x4e, 0xab, 0x96, 0x91, 0x70, 0x8d, 0x9e, 0xab, 0x05, 0xcd, 0x2c, 0x25, 0x69,
|
||||
0x90, 0xfc, 0xd3, 0xc3, 0x87, 0x4c, 0x53, 0xec, 0xbd, 0x0c, 0x7f, 0x1b, 0x46, 0x48, 0xbf, 0x5f,
|
||||
0x5d, 0x53, 0x61, 0x0e, 0x3c, 0x44, 0x7c, 0x45, 0x45, 0xf4, 0x0b, 0x18, 0xa8, 0xe6, 0xd8, 0x41,
|
||||
0xf7, 0xd6, 0x9d, 0xca, 0x2a, 0x31, 0x66, 0x2d, 0x21, 0xfa, 0x0e, 0x21, 0xb6, 0x87, 0x0d, 0xdc,
|
||||
0xc3, 0x7e, 0x04, 0x01, 0x32, 0x6b, 0xa3, 0xa2, 0xdf, 0xe9, 0x59, 0xf3, 0xaf, 0xb6, 0x4a, 0x56,
|
||||
0xb0, 0xd7, 0xd9, 0xb1, 0xdd, 0xc9, 0xeb, 0xee, 0xb4, 0x6d, 0xf4, 0xd0, 0x34, 0x36, 0x36, 0x47,
|
||||
0xc5, 0x32, 0xb6, 0x90, 0x2c, 0x35, 0x55, 0xd7, 0x62, 0x4b, 0x16, 0x7e, 0x4b, 0x16, 0xc9, 0x9f,
|
||||
0xbc, 0xed, 0x4e, 0x2a, 0x02, 0x2c, 0xda, 0x45, 0xb1, 0xd9, 0xd0, 0x3c, 0x35, 0x9b, 0x59, 0x88,
|
||||
0x99, 0x4c, 0xe7, 0x66, 0xb3, 0x5e, 0x3a, 0x47, 0x2c, 0x4a, 0x73, 0xa7, 0x3d, 0x51, 0x62, 0x35,
|
||||
0x6d, 0x18, 0xad, 0x6a, 0xc1, 0x36, 0x2c, 0x97, 0x66, 0x17, 0x57, 0x14, 0x7d, 0x00, 0x43, 0x49,
|
||||
0x57, 0x5f, 0x61, 0x0c, 0xe6, 0x6e, 0x25, 0x5d, 0x3d, 0x65, 0x4d, 0xf4, 0x1d, 0x08, 0x15, 0x83,
|
||||
0x2a, 0x95, 0xbe, 0xe0, 0x91, 0x12, 0x3c, 0x65, 0x4d, 0xf2, 0xd7, 0x1e, 0x0c, 0x66, 0x4c, 0x5c,
|
||||
0x33, 0xf1, 0x4e, 0x6f, 0xb6, 0x3b, 0x29, 0xf5, 0xdf, 0x32, 0x29, 0xf9, 0xbb, 0x27, 0xa5, 0x60,
|
||||
0x3b, 0x29, 0x3d, 0x80, 0x60, 0x26, 0x16, 0xe7, 0x67, 0x2a, 0xa2, 0x3e, 0xd1, 0x00, 0xeb, 0xf3,
|
||||
0x78, 0x21, 0xf9, 0x35, 0x33, 0xe3, 0x93, 0x41, 0xf7, 0x9e, 0xf2, 0xd1, 0x8e, 0x99, 0xe5, 0x7f,
|
||||
0x9d, 0xa2, 0x6c, 0xd3, 0x82, 0xd3, 0xb4, 0x09, 0x4c, 0x70, 0x94, 0x4a, 0xa9, 0xa4, 0x4f, 0x66,
|
||||
0x2f, 0x5f, 0xd8, 0xf9, 0xc9, 0x95, 0x25, 0x7f, 0xf4, 0x60, 0xf0, 0x8c, 0x36, 0x45, 0x2d, 0xef,
|
||||
0xd5, 0xff, 0x14, 0xc6, 0xc7, 0x65, 0x99, 0xf1, 0x45, 0xa7, 0xe7, 0x1d, 0x11, 0x5a, 0x3c, 0x77,
|
||||
0xee, 0x51, 0xe7, 0xd0, 0x15, 0xe1, 0x13, 0x73, 0xaa, 0xc6, 0x22, 0x3d, 0xe3, 0x38, 0x4f, 0x8c,
|
||||
0x9e, 0x86, 0x94, 0x12, 0x93, 0x7d, 0x5c, 0xcb, 0x62, 0x99, 0x15, 0x37, 0x2a, 0xab, 0x23, 0xd2,
|
||||
0xe2, 0xe4, 0x5f, 0x3d, 0xf0, 0xbf, 0xa9, 0x51, 0x66, 0x02, 0x1e, 0x37, 0x45, 0xe5, 0xf1, 0x76,
|
||||
0xb0, 0x19, 0x3a, 0x83, 0x4d, 0x0c, 0xc3, 0x46, 0xd0, 0x7c, 0xc5, 0xaa, 0x78, 0xa4, 0x78, 0xcd,
|
||||
0x42, 0xa5, 0x51, 0x1d, 0xac, 0x27, 0x9a, 0x90, 0x58, 0xd8, 0x76, 0x24, 0x38, 0x1d, 0xf9, 0x73,
|
||||
0x33, 0xfc, 0x8c, 0xef, 0x8e, 0x0b, 0xbb, 0x66, 0x9e, 0xff, 0xdf, 0x3b, 0xfe, 0x1f, 0x0f, 0x82,
|
||||
0xb6, 0x79, 0x4f, 0xbb, 0xcd, 0x7b, 0xba, 0x6d, 0xde, 0xb3, 0x13, 0xdb, 0xbc, 0x67, 0x27, 0x88,
|
||||
0xc9, 0x85, 0x6d, 0x5e, 0x72, 0x81, 0x97, 0xf5, 0x58, 0x14, 0x75, 0x79, 0xd2, 0xe8, 0x5b, 0x0d,
|
||||
0x49, 0x8b, 0xb1, 0xe2, 0x7f, 0xb3, 0x66, 0xc2, 0xa4, 0x3a, 0x24, 0x06, 0x61, 0x7f, 0x3c, 0x53,
|
||||
0x54, 0xa7, 0x93, 0xab, 0x41, 0xf4, 0x43, 0x08, 0x08, 0x26, 0x4f, 0x65, 0xb8, 0x73, 0x2f, 0x4a,
|
||||
0x4c, 0xb4, 0x16, 0x9d, 0xea, 0x4f, 0x22, 0xd3, 0x28, 0xf6, 0x03, 0xe9, 0x67, 0x30, 0x98, 0xad,
|
||||
0xf9, 0x52, 0xda, 0x11, 0xf2, 0x5b, 0x0e, 0x55, 0xf2, 0x0d, 0x53, 0x3a, 0x62, 0x4c, 0x92, 0x57,
|
||||
0x10, 0xb6, 0xc2, 0x6d, 0x38, 0x9e, 0x1b, 0x4e, 0x04, 0xfe, 0xeb, 0x9c, 0x4b, 0x4b, 0x11, 0xb8,
|
||||
0xc6, 0xc3, 0xbe, 0xaa, 0x69, 0x2e, 0xb9, 0x6c, 0x2c, 0x45, 0x58, 0x9c, 0x7c, 0x62, 0xc2, 0x47,
|
||||
0x77, 0xaf, 0xcb, 0x92, 0x09, 0x43, 0x37, 0x1a, 0xa8, 0x4d, 0x8a, 0x1b, 0xa6, 0xdf, 0x8e, 0x3e,
|
||||
0xd1, 0x20, 0xf9, 0x2d, 0x84, 0xc7, 0x19, 0x13, 0x92, 0xd4, 0x19, 0xdb, 0xf5, 0xa6, 0xab, 0x46,
|
||||
0x35, 0x11, 0xe0, 0x7a, 0x4b, 0x2d, 0xfd, 0x3b, 0xd4, 0xf2, 0x94, 0x96, 0xf4, 0xfc, 0x4c, 0xd5,
|
||||
0x79, 0x9f, 0x18, 0x94, 0xfc, 0xd9, 0x03, 0x1f, 0x39, 0xcc, 0x71, 0xed, 0xbf, 0x8d, 0xff, 0x2e,
|
||||
0x44, 0x71, 0xcd, 0x53, 0x26, 0xec, 0xe1, 0x2c, 0x56, 0x49, 0x5f, 0xac, 0x59, 0x3b, 0x3a, 0x18,
|
||||
0x84, 0xb5, 0x86, 0xdf, 0x4f, 0xb6, 0x97, 0x9c, 0x5a, 0x43, 0x31, 0xd1, 0x4a, 0x1c, 0x0f, 0x67,
|
||||
0x75, 0xc9, 0xc4, 0x71, 0xba, 0xe1, 0x76, 0xae, 0x72, 0x24, 0xc9, 0x17, 0xfa, 0x8b, 0xec, 0x1e,
|
||||
0x13, 0x7a, 0xbb, 0xbf, 0xde, 0xee, 0x46, 0x9e, 0xfc, 0xc5, 0x83, 0xe1, 0x73, 0x33, 0xc7, 0xb9,
|
||||
0xa7, 0xf0, 0xde, 0x78, 0x8a, 0x5e, 0xe7, 0x14, 0x47, 0xf0, 0xc0, 0xda, 0x74, 0xf6, 0xd7, 0x59,
|
||||
0xd8, 0xa9, 0x33, 0x19, 0xf5, 0xdb, 0xcb, 0x7a, 0x97, 0x0f, 0xb2, 0xcb, 0xae, 0xcd, 0xae, 0x0b,
|
||||
0xbf, 0x77, 0x2b, 0x53, 0x18, 0xdb, 0x0f, 0xd1, 0x22, 0xb3, 0x0f, 0x93, 0x2b, 0x4a, 0x8e, 0x60,
|
||||
0x70, 0x5a, 0xe4, 0x4b, 0xbe, 0x8a, 0x0e, 0xc1, 0x3f, 0xae, 0xe5, 0x5a, 0x79, 0x1c, 0x1f, 0x3d,
|
||||
0x70, 0x1a, 0xbf, 0x96, 0x6b, 0x6d, 0x43, 0x94, 0x45, 0xf2, 0x19, 0xc0, 0x56, 0x86, 0xaf, 0xcb,
|
||||
0xf6, 0x36, 0x5e, 0xb0, 0x1b, 0x2c, 0x99, 0xca, 0x8c, 0xf1, 0x3b, 0x34, 0xc9, 0xe7, 0x10, 0x9e,
|
||||
0xd4, 0x3c, 0x4b, 0xcf, 0xf3, 0x65, 0x81, 0xd4, 0x71, 0xc5, 0x44, 0xb5, 0xbd, 0x2f, 0x0b, 0x31,
|
||||
0xdd, 0xc8, 0x22, 0x6d, 0x0f, 0x19, 0x34, 0x1f, 0xa8, 0xbf, 0x39, 0x3e, 0xf9, 0x6f, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0x5f, 0x2f, 0x55, 0x31, 0xf8, 0x10, 0x00, 0x00,
|
||||
// 1807 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4b, 0x6f, 0xdc, 0xc8,
|
||||
0x11, 0x06, 0x67, 0x86, 0xa3, 0x61, 0x8d, 0x24, 0x0b, 0x1d, 0x63, 0x97, 0xbb, 0x09, 0x82, 0x09,
|
||||
0x91, 0x6c, 0x94, 0xc7, 0x3a, 0x0b, 0x19, 0x79, 0x60, 0xb1, 0xbb, 0x80, 0x1e, 0xb6, 0x23, 0x5b,
|
||||
0xb6, 0xe5, 0x96, 0xac, 0x9c, 0x82, 0x45, 0x8b, 0xec, 0x99, 0x69, 0x98, 0x43, 0x32, 0x4d, 0x52,
|
||||
0x12, 0x73, 0xce, 0xef, 0x08, 0x10, 0x20, 0xb9, 0x07, 0x41, 0x8e, 0x01, 0x72, 0xcf, 0x0f, 0xc8,
|
||||
0x5f, 0xc9, 0x35, 0xa8, 0x7e, 0x90, 0x4d, 0x69, 0x6c, 0x38, 0x40, 0xb0, 0xb7, 0xfe, 0xaa, 0x6a,
|
||||
0xaa, 0xab, 0xab, 0xab, 0xbe, 0x2e, 0x0e, 0x6c, 0x8b, 0xac, 0xe2, 0x32, 0x63, 0xe9, 0x83, 0x42,
|
||||
0xe6, 0x55, 0x4e, 0x26, 0x16, 0x47, 0x7f, 0x18, 0xc2, 0xf8, 0x2c, 0xaf, 0x65, 0xcc, 0xc9, 0x36,
|
||||
0x0c, 0x8e, 0x8f, 0x42, 0x6f, 0xe6, 0xed, 0x0e, 0xe9, 0xe0, 0xf8, 0x88, 0x10, 0x18, 0xbd, 0x60,
|
||||
0x2b, 0x1e, 0x0e, 0x66, 0xde, 0x6e, 0x40, 0xd5, 0x1a, 0x65, 0xe7, 0x4d, 0xc1, 0xc3, 0xa1, 0x96,
|
||||
0xe1, 0x9a, 0x7c, 0x0c, 0x93, 0xd7, 0x25, 0x7a, 0x5b, 0xf1, 0x70, 0xa4, 0xe4, 0x2d, 0x46, 0xdd,
|
||||
0x29, 0x2b, 0xcb, 0xeb, 0x5c, 0x26, 0xa1, 0xaf, 0x75, 0x16, 0x93, 0x1d, 0x18, 0xbe, 0xa6, 0x27,
|
||||
0xe1, 0x58, 0x89, 0x71, 0x49, 0x42, 0xd8, 0x38, 0xe2, 0x73, 0x56, 0xa7, 0x55, 0xb8, 0x31, 0xf3,
|
||||
0x76, 0x27, 0xd4, 0x42, 0xf4, 0x73, 0xce, 0x53, 0xbe, 0x90, 0x6c, 0x1e, 0x4e, 0xb4, 0x1f, 0x8b,
|
||||
0xc9, 0x03, 0x20, 0xc7, 0x59, 0xc9, 0xe3, 0x5a, 0xf2, 0xb3, 0x37, 0xa2, 0xb8, 0xe0, 0x52, 0xcc,
|
||||
0x9b, 0x30, 0x50, 0x0e, 0xd6, 0x68, 0x70, 0x97, 0xe7, 0xbc, 0x62, 0xb8, 0x37, 0x28, 0x57, 0x16,
|
||||
0x92, 0x08, 0x36, 0xcf, 0x96, 0x4c, 0xf2, 0xe4, 0x8c, 0xc7, 0x92, 0x57, 0xe1, 0x54, 0xa9, 0x7b,
|
||||
0x32, 0xb4, 0x79, 0x29, 0x17, 0x2c, 0x13, 0xbf, 0x67, 0x95, 0xc8, 0xb3, 0x70, 0x53, 0xdb, 0xb8,
|
||||
0x32, 0xcc, 0x12, 0xcd, 0x53, 0x1e, 0x6e, 0xe9, 0x2c, 0xe1, 0x9a, 0x7c, 0x07, 0x02, 0x73, 0x18,
|
||||
0x7a, 0x1a, 0x6e, 0x2b, 0x45, 0x27, 0x88, 0xfe, 0xee, 0x41, 0x70, 0xc4, 0xca, 0xe5, 0x65, 0xce,
|
||||
0x64, 0xf2, 0x5e, 0x37, 0xf1, 0x29, 0xf8, 0x31, 0x4f, 0xd3, 0x32, 0x1c, 0xce, 0x86, 0xbb, 0xd3,
|
||||
0xbd, 0x0f, 0x1f, 0xb4, 0x57, 0xdc, 0xfa, 0x39, 0xe4, 0x69, 0x4a, 0xb5, 0x15, 0xf9, 0x0c, 0x82,
|
||||
0x8a, 0xaf, 0x8a, 0x94, 0x55, 0xbc, 0x0c, 0x47, 0xea, 0x27, 0xa4, 0xfb, 0xc9, 0xb9, 0x51, 0xd1,
|
||||
0xce, 0xe8, 0xce, 0x41, 0xfd, 0xbb, 0x07, 0x8d, 0xfe, 0x3d, 0x82, 0xad, 0xde, 0x76, 0x64, 0x13,
|
||||
0xbc, 0x1b, 0x15, 0xb9, 0x4f, 0xbd, 0x1b, 0x44, 0x8d, 0x8a, 0xda, 0xa7, 0x5e, 0x83, 0xe8, 0x5a,
|
||||
0x55, 0x8e, 0x4f, 0xbd, 0x6b, 0x44, 0x4b, 0x55, 0x2f, 0x3e, 0xf5, 0x96, 0xe4, 0x47, 0xb0, 0xf1,
|
||||
0xbb, 0x9a, 0x4b, 0xc1, 0xcb, 0xd0, 0x57, 0xd1, 0xdd, 0xeb, 0xa2, 0x7b, 0x55, 0x73, 0xd9, 0x50,
|
||||
0xab, 0xc7, 0x6c, 0xa8, 0x5a, 0xd3, 0x85, 0xa3, 0xd6, 0x28, 0xab, 0xb0, 0x2e, 0x37, 0xb4, 0x0c,
|
||||
0xd7, 0x26, 0x8b, 0xba, 0x5a, 0x30, 0x8b, 0x3f, 0x87, 0x11, 0xbb, 0xe1, 0x65, 0x18, 0x28, 0xff,
|
||||
0xdf, 0x7b, 0x4b, 0xc2, 0x1e, 0xec, 0xdf, 0xf0, 0xf2, 0x51, 0x56, 0xc9, 0x86, 0x2a, 0x73, 0xf2,
|
||||
0x43, 0x18, 0xc7, 0x79, 0x9a, 0xcb, 0x32, 0x84, 0xdb, 0x81, 0x1d, 0xa2, 0x9c, 0x1a, 0x35, 0xd9,
|
||||
0x85, 0x71, 0xca, 0x17, 0x3c, 0x4b, 0x54, 0xdd, 0x4c, 0xf7, 0x76, 0x3a, 0xc3, 0x13, 0x25, 0xa7,
|
||||
0x46, 0x4f, 0x3e, 0x87, 0xcd, 0x8a, 0x5d, 0xa6, 0xfc, 0x65, 0x81, 0x59, 0x2c, 0x55, 0x0d, 0x4d,
|
||||
0xf7, 0x3e, 0x70, 0xee, 0xc3, 0xd1, 0xd2, 0x9e, 0x2d, 0xf9, 0x02, 0x36, 0xe7, 0x82, 0xa7, 0x89,
|
||||
0xfd, 0xed, 0x96, 0x0a, 0x2a, 0xec, 0x7e, 0x4b, 0x79, 0xc6, 0x56, 0xf8, 0x8b, 0xc7, 0x68, 0x46,
|
||||
0x7b, 0xd6, 0xe4, 0xbb, 0x00, 0x95, 0x58, 0xf1, 0xc7, 0xb9, 0x5c, 0xb1, 0xca, 0x94, 0xa1, 0x23,
|
||||
0x21, 0x5f, 0xc2, 0x56, 0xc2, 0x63, 0xb1, 0x62, 0xe9, 0x69, 0xca, 0x62, 0x5e, 0x86, 0xf7, 0x54,
|
||||
0x68, 0x6e, 0x75, 0xb9, 0x6a, 0xda, 0xb7, 0xfe, 0xf8, 0x09, 0x04, 0x6d, 0xfa, 0xb0, 0xbf, 0xdf,
|
||||
0xf0, 0x46, 0x15, 0x43, 0x40, 0x71, 0x49, 0xbe, 0x0f, 0xfe, 0x15, 0x4b, 0x6b, 0x5d, 0xc8, 0xd3,
|
||||
0xbd, 0xed, 0xce, 0xeb, 0xfe, 0x8d, 0x28, 0xa9, 0x56, 0x7e, 0x3e, 0xf8, 0x95, 0x17, 0x3d, 0x81,
|
||||
0xad, 0xde, 0x46, 0x18, 0xb8, 0x28, 0x1f, 0x65, 0xf3, 0x5c, 0xc6, 0x3c, 0x51, 0x3e, 0x27, 0xd4,
|
||||
0x91, 0x90, 0x0f, 0x60, 0x9c, 0x88, 0x85, 0xa8, 0x4a, 0x53, 0x6e, 0x06, 0x45, 0xff, 0xf0, 0x60,
|
||||
0xd3, 0xcd, 0x26, 0xf9, 0x31, 0xec, 0x5c, 0x71, 0x59, 0x89, 0x98, 0xa5, 0xe7, 0x62, 0xc5, 0x71,
|
||||
0x63, 0xf5, 0x93, 0x09, 0xbd, 0x23, 0x27, 0x9f, 0xc1, 0xb8, 0xcc, 0x65, 0x75, 0xd0, 0xa8, 0xaa,
|
||||
0x7d, 0x57, 0x96, 0x8d, 0x1d, 0xf2, 0xd4, 0xb5, 0x64, 0x45, 0x21, 0xb2, 0x85, 0xe5, 0x42, 0x8b,
|
||||
0xc9, 0x27, 0xb0, 0x3d, 0x17, 0x37, 0x8f, 0x85, 0x2c, 0xab, 0xc3, 0x3c, 0xad, 0x57, 0x99, 0xaa,
|
||||
0xe0, 0x09, 0xbd, 0x25, 0x7d, 0x3a, 0x9a, 0x78, 0x3b, 0x83, 0xa7, 0xa3, 0x89, 0xbf, 0x33, 0x8e,
|
||||
0x0a, 0xd8, 0xee, 0xef, 0x84, 0x6d, 0x69, 0x83, 0x50, 0x9c, 0xa0, 0xd3, 0xdb, 0x93, 0x91, 0x19,
|
||||
0x4c, 0x13, 0x51, 0x16, 0x29, 0x6b, 0x1c, 0xda, 0x70, 0x45, 0xc8, 0x81, 0x57, 0xa2, 0x14, 0x97,
|
||||
0xa9, 0xa6, 0xf2, 0x09, 0xb5, 0x30, 0x5a, 0x80, 0xaf, 0xca, 0xda, 0x21, 0xa1, 0xc0, 0x92, 0x90,
|
||||
0xa2, 0xfe, 0x81, 0x43, 0xfd, 0x3b, 0x30, 0xfc, 0x35, 0xbf, 0x31, 0xaf, 0x01, 0x2e, 0x5b, 0xaa,
|
||||
0x1a, 0x39, 0x54, 0x75, 0x1f, 0xfc, 0x0b, 0x75, 0xed, 0x9a, 0x42, 0x34, 0x88, 0xbe, 0x82, 0xb1,
|
||||
0x6e, 0x8b, 0xd6, 0xb3, 0xe7, 0x78, 0x9e, 0xc1, 0xf4, 0xa5, 0x14, 0x3c, 0xab, 0x34, 0xf9, 0x98,
|
||||
0x23, 0x38, 0xa2, 0xe8, 0x6f, 0x1e, 0x8c, 0xd4, 0x2d, 0x45, 0xb0, 0x99, 0xf2, 0x05, 0x8b, 0x9b,
|
||||
0x83, 0xbc, 0xce, 0x92, 0x32, 0xf4, 0x66, 0xc3, 0xdd, 0x21, 0xed, 0xc9, 0xb0, 0x3c, 0x2e, 0xb5,
|
||||
0x76, 0x30, 0x1b, 0xee, 0x06, 0xd4, 0x20, 0x0c, 0x2d, 0x65, 0x97, 0x3c, 0x35, 0x47, 0xd0, 0x00,
|
||||
0xad, 0x0b, 0xc9, 0xe7, 0xe2, 0xc6, 0x1c, 0xc3, 0x20, 0x94, 0x97, 0xf5, 0x1c, 0xe5, 0xfa, 0x24,
|
||||
0x06, 0xe1, 0x01, 0x2e, 0x59, 0xd9, 0x32, 0x12, 0xae, 0xd1, 0x73, 0x19, 0xb3, 0xd4, 0x52, 0x92,
|
||||
0x06, 0xd1, 0x3f, 0x3d, 0x7c, 0xc8, 0x34, 0xc5, 0xde, 0xc9, 0xf0, 0x47, 0x30, 0x41, 0xfa, 0xfd,
|
||||
0xfa, 0x8a, 0x49, 0x73, 0xe0, 0x0d, 0xc4, 0x17, 0x4c, 0x92, 0x9f, 0xc1, 0x58, 0x35, 0xc7, 0x1a,
|
||||
0xba, 0xb7, 0xee, 0x54, 0x56, 0xa9, 0x31, 0x6b, 0x09, 0x71, 0xe4, 0x10, 0x62, 0x7b, 0x58, 0xdf,
|
||||
0x3d, 0xec, 0xa7, 0xe0, 0x23, 0xb3, 0x36, 0x2a, 0xfa, 0xb5, 0x9e, 0x35, 0xff, 0x6a, 0xab, 0x68,
|
||||
0x01, 0x5b, 0xbd, 0x1d, 0xdb, 0x9d, 0xbc, 0xfe, 0x4e, 0x5d, 0xa3, 0x07, 0xa6, 0xb1, 0xb1, 0x39,
|
||||
0x4a, 0x9e, 0xf2, 0xb8, 0xe2, 0x89, 0xa9, 0xba, 0x16, 0x5b, 0xb2, 0x18, 0xb5, 0x64, 0x11, 0xfd,
|
||||
0xc9, 0xeb, 0x76, 0x52, 0x11, 0x60, 0xd1, 0xc6, 0xf9, 0x6a, 0xc5, 0xb2, 0xc4, 0x6c, 0x66, 0x21,
|
||||
0x66, 0x32, 0xb9, 0x34, 0x9b, 0x0d, 0x92, 0x4b, 0xc4, 0xb2, 0x30, 0x77, 0x3a, 0x90, 0x05, 0x56,
|
||||
0xd3, 0x8a, 0xb3, 0xb2, 0x96, 0x7c, 0xc5, 0xb3, 0xca, 0xec, 0xe2, 0x8a, 0xc8, 0x87, 0xb0, 0x51,
|
||||
0xb1, 0xc5, 0xd7, 0x18, 0x83, 0xb9, 0xdb, 0x8a, 0x2d, 0x9e, 0xf1, 0x86, 0x7c, 0x1b, 0x02, 0xc5,
|
||||
0xa0, 0x4a, 0xa5, 0x2f, 0x78, 0xa2, 0x04, 0xcf, 0x78, 0x13, 0xfd, 0x75, 0x00, 0xe3, 0x33, 0x2e,
|
||||
0xaf, 0xb8, 0x7c, 0xaf, 0x37, 0xdb, 0x9d, 0x94, 0x86, 0xef, 0x98, 0x94, 0x46, 0xeb, 0x27, 0x25,
|
||||
0xbf, 0x9b, 0x94, 0xee, 0x83, 0x7f, 0x26, 0xe3, 0xe3, 0x23, 0x15, 0xd1, 0x90, 0x6a, 0x80, 0xf5,
|
||||
0xb9, 0x1f, 0x57, 0xe2, 0x8a, 0x9b, 0xf1, 0xc9, 0xa0, 0x3b, 0x4f, 0xf9, 0x64, 0xcd, 0xcc, 0xf2,
|
||||
0xbf, 0x4e, 0x51, 0xb6, 0x69, 0xc1, 0x69, 0xda, 0x08, 0x36, 0x71, 0x94, 0x4a, 0x58, 0xc5, 0x9e,
|
||||
0x9e, 0xbd, 0x7c, 0x61, 0xe7, 0x27, 0x57, 0x16, 0xfd, 0xd1, 0x83, 0xf1, 0x09, 0x6b, 0xf2, 0xba,
|
||||
0xba, 0x53, 0xff, 0x33, 0x98, 0xee, 0x17, 0x45, 0x2a, 0xe2, 0x5e, 0xcf, 0x3b, 0x22, 0xb4, 0x78,
|
||||
0xee, 0xdc, 0xa3, 0xce, 0xa1, 0x2b, 0xc2, 0x27, 0xe6, 0x50, 0x8d, 0x45, 0x7a, 0xc6, 0x71, 0x9e,
|
||||
0x18, 0x3d, 0x0d, 0x29, 0x25, 0x26, 0x7b, 0xbf, 0xae, 0xf2, 0x79, 0x9a, 0x5f, 0xab, 0xac, 0x4e,
|
||||
0x68, 0x8b, 0xa3, 0x7f, 0x0d, 0x60, 0xf4, 0x4d, 0x8d, 0x32, 0x9b, 0xe0, 0x09, 0x53, 0x54, 0x9e,
|
||||
0x68, 0x07, 0x9b, 0x0d, 0x67, 0xb0, 0x09, 0x61, 0xa3, 0x91, 0x2c, 0x5b, 0xf0, 0x32, 0x9c, 0x28,
|
||||
0x5e, 0xb3, 0x50, 0x69, 0x54, 0x07, 0xeb, 0x89, 0x26, 0xa0, 0x16, 0xb6, 0x1d, 0x09, 0x4e, 0x47,
|
||||
0xfe, 0xd4, 0x0c, 0x3f, 0xd3, 0xdb, 0xe3, 0xc2, 0xba, 0x99, 0xe7, 0xff, 0xf7, 0x8e, 0xff, 0xc7,
|
||||
0x03, 0xbf, 0x6d, 0xde, 0xc3, 0x7e, 0xf3, 0x1e, 0x76, 0xcd, 0x7b, 0x74, 0x60, 0x9b, 0xf7, 0xe8,
|
||||
0x00, 0x31, 0x3d, 0xb5, 0xcd, 0x4b, 0x4f, 0xf1, 0xb2, 0x9e, 0xc8, 0xbc, 0x2e, 0x0e, 0x1a, 0x7d,
|
||||
0xab, 0x01, 0x6d, 0x31, 0x56, 0xfc, 0x6f, 0x96, 0x5c, 0x9a, 0x54, 0x07, 0xd4, 0x20, 0xec, 0x8f,
|
||||
0x13, 0x45, 0x75, 0x3a, 0xb9, 0x1a, 0x90, 0x1f, 0x80, 0x4f, 0x31, 0x79, 0x2a, 0xc3, 0xbd, 0x7b,
|
||||
0x51, 0x62, 0xaa, 0xb5, 0xe8, 0x54, 0x7f, 0x12, 0x99, 0x46, 0xb1, 0x1f, 0x48, 0x3f, 0x81, 0xf1,
|
||||
0xd9, 0x52, 0xcc, 0x2b, 0x3b, 0x42, 0x7e, 0xcb, 0xa1, 0x4a, 0xb1, 0xe2, 0x4a, 0x47, 0x8d, 0x49,
|
||||
0xf4, 0x0a, 0x82, 0x56, 0xd8, 0x85, 0xe3, 0xb9, 0xe1, 0x10, 0x18, 0xbd, 0xce, 0x44, 0x65, 0x29,
|
||||
0x02, 0xd7, 0x78, 0xd8, 0x57, 0x35, 0xcb, 0x2a, 0x51, 0x35, 0x96, 0x22, 0x2c, 0x8e, 0x1e, 0x9a,
|
||||
0xf0, 0xd1, 0xdd, 0xeb, 0xa2, 0xe0, 0xd2, 0xd0, 0x8d, 0x06, 0x6a, 0x93, 0xfc, 0x9a, 0xeb, 0xb7,
|
||||
0x63, 0x48, 0x35, 0x88, 0x7e, 0x0b, 0xc1, 0x7e, 0xca, 0x65, 0x45, 0xeb, 0x94, 0xaf, 0x7b, 0xd3,
|
||||
0x55, 0xa3, 0x9a, 0x08, 0x70, 0xdd, 0x51, 0xcb, 0xf0, 0x16, 0xb5, 0x3c, 0x63, 0x05, 0x3b, 0x3e,
|
||||
0x52, 0x75, 0x3e, 0xa4, 0x06, 0x45, 0x7f, 0xf6, 0x60, 0x84, 0x1c, 0xe6, 0xb8, 0x1e, 0xbd, 0x8b,
|
||||
0xff, 0x4e, 0x65, 0x7e, 0x25, 0x12, 0x2e, 0xed, 0xe1, 0x2c, 0x56, 0x49, 0x8f, 0x97, 0xbc, 0x1d,
|
||||
0x1d, 0x0c, 0xc2, 0x5a, 0xc3, 0xef, 0x27, 0xdb, 0x4b, 0x4e, 0xad, 0xa1, 0x98, 0x6a, 0x25, 0x8e,
|
||||
0x87, 0x67, 0x75, 0xc1, 0xe5, 0x7e, 0xb2, 0x12, 0x76, 0xae, 0x72, 0x24, 0xd1, 0x57, 0xfa, 0x8b,
|
||||
0xec, 0x0e, 0x13, 0x7a, 0xeb, 0xbf, 0xde, 0x6e, 0x47, 0x1e, 0xfd, 0xc5, 0x83, 0x8d, 0xe7, 0x66,
|
||||
0x8e, 0x73, 0x4f, 0xe1, 0xbd, 0xf5, 0x14, 0x83, 0xde, 0x29, 0xf6, 0xe0, 0xbe, 0xb5, 0xe9, 0xed,
|
||||
0xaf, 0xb3, 0xb0, 0x56, 0x67, 0x32, 0x3a, 0x6a, 0x2f, 0xeb, 0x7d, 0x3e, 0xc8, 0xce, 0xfb, 0x36,
|
||||
0xeb, 0x2e, 0xfc, 0xce, 0xad, 0xcc, 0x60, 0x6a, 0x3f, 0x44, 0xf3, 0xd4, 0x3e, 0x4c, 0xae, 0x28,
|
||||
0xda, 0x83, 0xf1, 0x61, 0x9e, 0xcd, 0xc5, 0x82, 0xec, 0xc2, 0x68, 0xbf, 0xae, 0x96, 0xca, 0xe3,
|
||||
0x74, 0xef, 0xbe, 0xd3, 0xf8, 0x75, 0xb5, 0xd4, 0x36, 0x54, 0x59, 0x44, 0x5f, 0x00, 0x74, 0x32,
|
||||
0x7c, 0x5d, 0xba, 0xdb, 0x78, 0xc1, 0xaf, 0xb1, 0x64, 0x4a, 0x33, 0xc6, 0xaf, 0xd1, 0x44, 0x35,
|
||||
0x10, 0xf7, 0x1c, 0xc6, 0xcb, 0x27, 0xb0, 0xed, 0x4a, 0xdb, 0x93, 0xdd, 0x92, 0x92, 0x5f, 0x42,
|
||||
0x70, 0x92, 0x2f, 0x2e, 0x04, 0xb7, 0xdd, 0x30, 0xdd, 0xfb, 0xc8, 0xf9, 0x18, 0xb3, 0x2a, 0x13,
|
||||
0x6f, 0x67, 0x1b, 0x3d, 0x86, 0x7b, 0xb7, 0xb4, 0xe4, 0x21, 0xf2, 0x16, 0xce, 0xe5, 0x7a, 0xb0,
|
||||
0x7c, 0x9b, 0x27, 0xb4, 0xa0, 0xd6, 0x32, 0x6a, 0x7a, 0x7e, 0x50, 0xd6, 0x66, 0xde, 0xbb, 0xd5,
|
||||
0x0f, 0x79, 0x29, 0xda, 0xd7, 0xce, 0xa7, 0x2d, 0x26, 0xbf, 0x80, 0xe0, 0x51, 0x16, 0xe7, 0x89,
|
||||
0xc8, 0x16, 0x76, 0xe8, 0x0b, 0x7b, 0x5f, 0x9e, 0xf5, 0x2a, 0xb3, 0x06, 0xb4, 0x33, 0x8d, 0x5e,
|
||||
0xc0, 0x76, 0x5f, 0xb9, 0x76, 0xbc, 0x6e, 0x47, 0xf2, 0x81, 0x33, 0x92, 0xb7, 0x31, 0x0e, 0x9d,
|
||||
0xca, 0xff, 0x12, 0x82, 0x83, 0x5a, 0xa4, 0xc9, 0x71, 0x36, 0xcf, 0x91, 0xc4, 0x2f, 0xb8, 0x2c,
|
||||
0xbb, 0xce, 0xb1, 0x10, 0x0b, 0x1f, 0xf9, 0xbc, 0x65, 0x33, 0x83, 0x2e, 0xc7, 0xea, 0x0f, 0xa7,
|
||||
0x87, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x58, 0xd6, 0x93, 0x3e, 0x82, 0x12, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -214,6 +214,27 @@ message AuthConfig {
|
|||
bool SuperAdminNewUsers = 1; // SuperAdminNewUsers configuration option that specifies which users will auto become super admin
|
||||
}
|
||||
|
||||
message OrganizationConfig {
|
||||
string OrganizationID = 1; // OrganizationID is the ID of the organization this config belogs to
|
||||
LogViewerConfig LogViewer = 2; // LogViewer is the organization configuration for log viewer
|
||||
}
|
||||
|
||||
message LogViewerConfig {
|
||||
repeated LogViewerColumn Columns = 1; // Columns is the array of columns in the log viewer
|
||||
}
|
||||
|
||||
message LogViewerColumn {
|
||||
string Name = 1; // Name is the unique identifier of the log viewer column
|
||||
int32 Position = 2; // Position is the position of the column in the log viewer's array of columns
|
||||
repeated ColumnEncoding Encodings = 3; // Encodings is the array of encoded properties associated with a log viewer column
|
||||
}
|
||||
|
||||
message ColumnEncoding {
|
||||
string Type = 1; // Type is the purpose of the encoding, for example: severity color
|
||||
string Value = 2; // Value is what the encoding corresponds to
|
||||
string Name = 3; // Name is the optional encoding name
|
||||
}
|
||||
|
||||
message BuildInfo {
|
||||
string Version = 1; // Version is a descriptive git SHA identifier
|
||||
string Commit = 2; // Commit is an abbreviated SHA
|
||||
|
|
|
@ -0,0 +1,236 @@
|
|||
package bolt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/influxdata/chronograf"
|
||||
"github.com/influxdata/chronograf/bolt/internal"
|
||||
)
|
||||
|
||||
// Ensure OrganizationConfigStore implements chronograf.OrganizationConfigStore.
|
||||
var _ chronograf.OrganizationConfigStore = &OrganizationConfigStore{}
|
||||
|
||||
// OrganizationConfigBucket is used to store chronograf organization configurations
|
||||
var OrganizationConfigBucket = []byte("OrganizationConfigV1")
|
||||
|
||||
// OrganizationConfigStore uses bolt to store and retrieve organization configurations
|
||||
type OrganizationConfigStore struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (s *OrganizationConfigStore) Migrate(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get retrieves an OrganizationConfig from the store
|
||||
func (s *OrganizationConfigStore) Get(ctx context.Context, orgID string) (*chronograf.OrganizationConfig, error) {
|
||||
var c chronograf.OrganizationConfig
|
||||
|
||||
err := s.client.db.View(func(tx *bolt.Tx) error {
|
||||
return s.get(ctx, tx, orgID, &c)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
func (s *OrganizationConfigStore) get(ctx context.Context, tx *bolt.Tx, orgID string, c *chronograf.OrganizationConfig) error {
|
||||
v := tx.Bucket(OrganizationConfigBucket).Get([]byte(orgID))
|
||||
if len(v) == 0 {
|
||||
return chronograf.ErrOrganizationConfigNotFound
|
||||
}
|
||||
return internal.UnmarshalOrganizationConfig(v, c)
|
||||
}
|
||||
|
||||
// FindOrCreate gets an OrganizationConfig from the store or creates one if none exists for this organization
|
||||
func (s *OrganizationConfigStore) FindOrCreate(ctx context.Context, orgID string) (*chronograf.OrganizationConfig, error) {
|
||||
var c chronograf.OrganizationConfig
|
||||
err := s.client.db.Update(func(tx *bolt.Tx) error {
|
||||
err := s.get(ctx, tx, orgID, &c)
|
||||
if err == chronograf.ErrOrganizationConfigNotFound {
|
||||
c = newOrganizationConfig(orgID)
|
||||
return s.put(ctx, tx, &c)
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
// Put replaces the OrganizationConfig in the store
|
||||
func (s *OrganizationConfigStore) Put(ctx context.Context, c *chronograf.OrganizationConfig) error {
|
||||
return s.client.db.Update(func(tx *bolt.Tx) error {
|
||||
return s.put(ctx, tx, c)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *OrganizationConfigStore) put(ctx context.Context, tx *bolt.Tx, c *chronograf.OrganizationConfig) error {
|
||||
if c == nil {
|
||||
return fmt.Errorf("config provided was nil")
|
||||
}
|
||||
if v, err := internal.MarshalOrganizationConfig(c); err != nil {
|
||||
return err
|
||||
} else if err := tx.Bucket(OrganizationConfigBucket).Put([]byte(c.OrganizationID), v); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newOrganizationConfig(orgID string) chronograf.OrganizationConfig {
|
||||
return chronograf.OrganizationConfig{
|
||||
OrganizationID: orgID,
|
||||
LogViewer: chronograf.LogViewerConfig{
|
||||
Columns: []chronograf.LogViewerColumn{
|
||||
{
|
||||
Name: "time",
|
||||
Position: 0,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "hidden",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "severity",
|
||||
Position: 1,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "visible",
|
||||
},
|
||||
{
|
||||
Type: "label",
|
||||
Value: "icon",
|
||||
},
|
||||
{
|
||||
Type: "label",
|
||||
Value: "text",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "emerg",
|
||||
Value: "ruby",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "alert",
|
||||
Value: "fire",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "crit",
|
||||
Value: "curacao",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "err",
|
||||
Value: "tiger",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "warning",
|
||||
Value: "pineapple",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "notice",
|
||||
Value: "rainforest",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "info",
|
||||
Value: "star",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "debug",
|
||||
Value: "wolf",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "timestamp",
|
||||
Position: 2,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "visible",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "message",
|
||||
Position: 3,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "visible",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "facility",
|
||||
Position: 4,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "visible",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "procid",
|
||||
Position: 5,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "visible",
|
||||
},
|
||||
{
|
||||
Type: "displayName",
|
||||
Value: "Proc ID",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "appname",
|
||||
Position: 6,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "visible",
|
||||
},
|
||||
{
|
||||
Type: "displayName",
|
||||
Value: "Application",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "host",
|
||||
Position: 7,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "visible",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -13,10 +13,15 @@
|
|||
"name": "MySQL – Reads/Second",
|
||||
"queries": [
|
||||
{
|
||||
"query": "SELECT non_negative_derivative(last(\"commands_select\"), 1s) AS selects_per_second FROM \":db:\".\":rp:\".\"mysql\"",
|
||||
"groupbys": [
|
||||
"\"server\""
|
||||
],
|
||||
"query":
|
||||
"SELECT non_negative_derivative(last(\"commands_select\"), 1s) AS selects_per_second FROM \":db:\".\":rp:\".\"mysql\"",
|
||||
"groupbys": ["\"server\""],
|
||||
"wheres": []
|
||||
},
|
||||
{
|
||||
"query":
|
||||
"SELECT non_negative_derivative(last(\"com_select\"), 1s) AS selects_per_second FROM \":db:\".\":rp:\".\"mysql\"",
|
||||
"groupbys": ["\"server\""],
|
||||
"wheres": []
|
||||
}
|
||||
]
|
||||
|
@ -30,10 +35,15 @@
|
|||
"name": "MySQL – Writes/Second",
|
||||
"queries": [
|
||||
{
|
||||
"query": "SELECT non_negative_derivative(last(\"commands_insert\"), 1s) AS inserts_per_second, non_negative_derivative(last(\"commands_update\"), 1s) AS updates_per_second, non_negative_derivative(last(\"commands_delete\"), 1s) AS deletes_per_second FROM \":db:\".\":rp:\".\"mysql\"",
|
||||
"groupbys": [
|
||||
"\"server\""
|
||||
],
|
||||
"query":
|
||||
"SELECT non_negative_derivative(last(\"commands_insert\"), 1s) AS inserts_per_second, non_negative_derivative(last(\"commands_update\"), 1s) AS updates_per_second, non_negative_derivative(last(\"commands_delete\"), 1s) AS deletes_per_second FROM \":db:\".\":rp:\".\"mysql\"",
|
||||
"groupbys": ["\"server\""],
|
||||
"wheres": []
|
||||
},
|
||||
{
|
||||
"query":
|
||||
"SELECT non_negative_derivative(last(\"com_insert\"), 1s) AS inserts_per_second, non_negative_derivative(last(\"com_update\"), 1s) AS updates_per_second, non_negative_derivative(last(\"com_delete\"), 1s) AS deletes_per_second FROM \":db:\".\":rp:\".\"mysql\"",
|
||||
"groupbys": ["\"server\""],
|
||||
"wheres": []
|
||||
}
|
||||
]
|
||||
|
@ -47,10 +57,9 @@
|
|||
"name": "MySQL – Connections/Second",
|
||||
"queries": [
|
||||
{
|
||||
"query": "SELECT non_negative_derivative(last(\"threads_connected\"), 1s) AS cxn_per_second, non_negative_derivative(last(\"threads_running\"), 1s) AS threads_running_per_second FROM \":db:\".\":rp:\".\"mysql\"",
|
||||
"groupbys": [
|
||||
"\"server\""
|
||||
],
|
||||
"query":
|
||||
"SELECT non_negative_derivative(last(\"threads_connected\"), 1s) AS cxn_per_second, non_negative_derivative(last(\"threads_running\"), 1s) AS threads_running_per_second FROM \":db:\".\":rp:\".\"mysql\"",
|
||||
"groupbys": ["\"server\""],
|
||||
"wheres": []
|
||||
}
|
||||
]
|
||||
|
@ -64,10 +73,9 @@
|
|||
"name": "MySQL – Connections Errors/Second",
|
||||
"queries": [
|
||||
{
|
||||
"query": "SELECT non_negative_derivative(last(\"connection_errors_max_connections\"), 1s) AS cxn_errors_per_second, non_negative_derivative(last(\"connection_errors_internal\"), 1s) AS internal_cxn_errors_per_second, non_negative_derivative(last(\"aborted_connects\"), 1s) AS cxn_aborted_per_second FROM \":db:\".\":rp:\".\"mysql\"",
|
||||
"groupbys": [
|
||||
"\"server\""
|
||||
],
|
||||
"query":
|
||||
"SELECT non_negative_derivative(last(\"connection_errors_max_connections\"), 1s) AS cxn_errors_per_second, non_negative_derivative(last(\"connection_errors_internal\"), 1s) AS internal_cxn_errors_per_second, non_negative_derivative(last(\"aborted_connects\"), 1s) AS cxn_aborted_per_second FROM \":db:\".\":rp:\".\"mysql\"",
|
||||
"groupbys": ["\"server\""],
|
||||
"wheres": []
|
||||
}
|
||||
]
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
{
|
||||
"query": "select max(\"percent_packet_loss\") as \"packet_loss\" from ping",
|
||||
"groupbys": [
|
||||
"\"server\""
|
||||
"\"url\""
|
||||
],
|
||||
"wheres": []
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
|||
{
|
||||
"query": "select mean(\"average_response_ms\") as \"average\", mean(\"minimum_response_ms\") as \"min\", mean(\"maximum_response_ms\") as \"max\" from ping",
|
||||
"groupbys": [
|
||||
"\"server\""
|
||||
"\"url\""
|
||||
],
|
||||
"wheres": []
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ const (
|
|||
ErrInvalidCellOptionsText = Error("invalid text wrapping option. Valid wrappings are 'truncate', 'wrap', and 'single line'")
|
||||
ErrInvalidCellOptionsSort = Error("cell options sortby cannot be empty'")
|
||||
ErrInvalidCellOptionsColumns = Error("cell options columns cannot be empty'")
|
||||
ErrOrganizationConfigNotFound = Error("could not find organization config")
|
||||
)
|
||||
|
||||
// Error is a domain error encountered while processing chronograf requests
|
||||
|
@ -736,22 +737,18 @@ type OrganizationsStore interface {
|
|||
DefaultOrganization(ctx context.Context) (*Organization, error)
|
||||
}
|
||||
|
||||
// AuthConfig is the global application config section for auth parameters
|
||||
type AuthConfig struct {
|
||||
// SuperAdminNewUsers should be true by default to give a seamless upgrade to
|
||||
// 1.4.0 for legacy users. It means that all new users will by default receive
|
||||
// SuperAdmin status. If a SuperAdmin wants to change this behavior, they
|
||||
// can toggle it off via the Chronograf UI, in which case newly authenticating
|
||||
// users will simply receive whatever role they would otherwise receive.
|
||||
SuperAdminNewUsers bool `json:"superAdminNewUsers"`
|
||||
}
|
||||
|
||||
// Config is the global application Config for parameters that can be set via
|
||||
// API, with different sections, such as Auth
|
||||
type Config struct {
|
||||
Auth AuthConfig `json:"auth"`
|
||||
}
|
||||
|
||||
// AuthConfig is the global application config section for auth parameters
|
||||
type AuthConfig struct {
|
||||
// SuperAdminNewUsers configuration option that specifies which users will auto become super admin
|
||||
SuperAdminNewUsers bool `json:"superAdminNewUsers"`
|
||||
}
|
||||
|
||||
// ConfigStore is the storage and retrieval of global application Config
|
||||
type ConfigStore interface {
|
||||
// Initialize creates the initial configuration
|
||||
|
@ -762,6 +759,40 @@ type ConfigStore interface {
|
|||
Update(context.Context, *Config) error
|
||||
}
|
||||
|
||||
// OrganizationConfig is the organization config for parameters that can
|
||||
// be set via API, with different sections, such as LogViewer
|
||||
type OrganizationConfig struct {
|
||||
OrganizationID string `json:"organization"`
|
||||
LogViewer LogViewerConfig `json:"logViewer"`
|
||||
}
|
||||
|
||||
// LogViewerConfig is the configuration settings for the Log Viewer UI
|
||||
type LogViewerConfig struct {
|
||||
Columns []LogViewerColumn `json:"columns"`
|
||||
}
|
||||
|
||||
// LogViewerColumn is a specific column of the Log Viewer UI
|
||||
type LogViewerColumn struct {
|
||||
Name string `json:"name"`
|
||||
Position int32 `json:"position"`
|
||||
Encodings []ColumnEncoding `json:"encodings"`
|
||||
}
|
||||
|
||||
// ColumnEncoding is the settings for a specific column of the Log Viewer UI
|
||||
type ColumnEncoding struct {
|
||||
Type string `json:"type"`
|
||||
Value string `json:"value"`
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
// OrganizationConfigStore is the storage and retrieval of organization Configs
|
||||
type OrganizationConfigStore interface {
|
||||
// FindOrCreate gets an existing OrganizationConfig and creates one if none exists
|
||||
FindOrCreate(ctx context.Context, orgID string) (*OrganizationConfig, error)
|
||||
// Put replaces the whole organization config in the OrganizationConfigStore
|
||||
Put(context.Context, *OrganizationConfig) error
|
||||
}
|
||||
|
||||
// BuildInfo is sent to the usage client to track versions and commits
|
||||
type BuildInfo struct {
|
||||
Version string
|
||||
|
|
|
@ -2657,6 +2657,705 @@ func TestServer(t *testing.T) {
|
|||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "GET /org_config",
|
||||
subName: "default org",
|
||||
fields: fields{
|
||||
Users: []chronograf.User{
|
||||
{
|
||||
ID: 1, // This is artificial, but should be reflective of the users actual ID
|
||||
Name: "billibob",
|
||||
Provider: "github",
|
||||
Scheme: "oauth2",
|
||||
SuperAdmin: true,
|
||||
Roles: []chronograf.Role{
|
||||
{
|
||||
Name: "admin",
|
||||
Organization: "default",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
server: &server.Server{
|
||||
GithubClientID: "not empty",
|
||||
GithubClientSecret: "not empty",
|
||||
},
|
||||
method: "GET",
|
||||
path: "/chronograf/v1/org_config",
|
||||
principal: oauth2.Principal{
|
||||
Organization: "default",
|
||||
Subject: "billibob",
|
||||
Issuer: "github",
|
||||
},
|
||||
},
|
||||
wants: wants{
|
||||
statusCode: 200,
|
||||
body: `
|
||||
{
|
||||
"links": {
|
||||
"self": "\/chronograf\/v1\/org_config",
|
||||
"logViewer": "\/chronograf\/v1\/org_config\/logviewer"
|
||||
},
|
||||
"organization": "default",
|
||||
"logViewer": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "time",
|
||||
"position": 0,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "hidden"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "severity",
|
||||
"position": 1,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"value": "icon"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"value": "text"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "ruby",
|
||||
"name": "emerg"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "fire",
|
||||
"name": "alert"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "curacao",
|
||||
"name": "crit"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "tiger",
|
||||
"name": "err"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "pineapple",
|
||||
"name": "warning"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "rainforest",
|
||||
"name": "notice"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "star",
|
||||
"name": "info"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "wolf",
|
||||
"name": "debug"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "timestamp",
|
||||
"position": 2,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "message",
|
||||
"position": 3,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "facility",
|
||||
"position": 4,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "procid",
|
||||
"position": 5,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
},
|
||||
{
|
||||
"type": "displayName",
|
||||
"value": "Proc ID"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "appname",
|
||||
"position": 6,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
},
|
||||
{
|
||||
"type": "displayName",
|
||||
"value": "Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "host",
|
||||
"position": 7,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "GET /org_config/logviewer",
|
||||
subName: "default org",
|
||||
fields: fields{
|
||||
Users: []chronograf.User{
|
||||
{
|
||||
ID: 1, // This is artificial, but should be reflective of the users actual ID
|
||||
Name: "billibob",
|
||||
Provider: "github",
|
||||
Scheme: "oauth2",
|
||||
SuperAdmin: true,
|
||||
Roles: []chronograf.Role{
|
||||
{
|
||||
Name: "admin",
|
||||
Organization: "default",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
server: &server.Server{
|
||||
GithubClientID: "not empty",
|
||||
GithubClientSecret: "not empty",
|
||||
},
|
||||
method: "GET",
|
||||
path: "/chronograf/v1/org_config/logviewer",
|
||||
principal: oauth2.Principal{
|
||||
Organization: "default",
|
||||
Subject: "billibob",
|
||||
Issuer: "github",
|
||||
},
|
||||
},
|
||||
wants: wants{
|
||||
statusCode: 200,
|
||||
body: `
|
||||
{
|
||||
"links": {
|
||||
"self": "\/chronograf\/v1\/org_config/logviewer"
|
||||
},
|
||||
"columns": [
|
||||
{
|
||||
"name": "time",
|
||||
"position": 0,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "hidden"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "severity",
|
||||
"position": 1,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"value": "icon"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"value": "text"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "ruby",
|
||||
"name": "emerg"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "fire",
|
||||
"name": "alert"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "curacao",
|
||||
"name": "crit"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "tiger",
|
||||
"name": "err"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "pineapple",
|
||||
"name": "warning"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "rainforest",
|
||||
"name": "notice"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "star",
|
||||
"name": "info"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "wolf",
|
||||
"name": "debug"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "timestamp",
|
||||
"position": 2,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "message",
|
||||
"position": 3,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "facility",
|
||||
"position": 4,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "procid",
|
||||
"position": 5,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
},
|
||||
{
|
||||
"type": "displayName",
|
||||
"value": "Proc ID"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "appname",
|
||||
"position": 6,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
},
|
||||
{
|
||||
"type": "displayName",
|
||||
"value": "Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "host",
|
||||
"position": 7,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "PUT /org_config/logviewer",
|
||||
subName: "default org",
|
||||
fields: fields{
|
||||
Config: &chronograf.Config{
|
||||
Auth: chronograf.AuthConfig{
|
||||
SuperAdminNewUsers: true,
|
||||
},
|
||||
},
|
||||
Organizations: []chronograf.Organization{
|
||||
{
|
||||
ID: "1",
|
||||
Name: "cool",
|
||||
DefaultRole: roles.ViewerRoleName,
|
||||
},
|
||||
},
|
||||
Users: []chronograf.User{
|
||||
{
|
||||
ID: 1, // This is artificial, but should be reflective of the users actual ID
|
||||
Name: "billibob",
|
||||
Provider: "github",
|
||||
Scheme: "oauth2",
|
||||
SuperAdmin: true,
|
||||
Roles: []chronograf.Role{
|
||||
{
|
||||
Name: "admin",
|
||||
Organization: "default",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
server: &server.Server{
|
||||
GithubClientID: "not empty",
|
||||
GithubClientSecret: "not empty",
|
||||
},
|
||||
method: "PUT",
|
||||
path: "/chronograf/v1/org_config/logviewer",
|
||||
payload: &chronograf.LogViewerConfig{
|
||||
Columns: []chronograf.LogViewerColumn{
|
||||
{
|
||||
Name: "time",
|
||||
Position: 0,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "hidden",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "severity",
|
||||
Position: 1,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "visible",
|
||||
},
|
||||
{
|
||||
Type: "label",
|
||||
Value: "icon",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "emerg",
|
||||
Value: "ruby",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "alert",
|
||||
Value: "fire",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "crit",
|
||||
Value: "curacao",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "err",
|
||||
Value: "tiger",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "warning",
|
||||
Value: "pineapple",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "notice",
|
||||
Value: "wolf",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "info",
|
||||
Value: "wolf",
|
||||
},
|
||||
{
|
||||
Type: "color",
|
||||
Name: "debug",
|
||||
Value: "wolf",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "timestamp",
|
||||
Position: 3,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "visible",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "message",
|
||||
Position: 2,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "visible",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "facility",
|
||||
Position: 4,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "visible",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "procid",
|
||||
Position: 5,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "hidden",
|
||||
},
|
||||
{
|
||||
Type: "displayName",
|
||||
Value: "ProcID!",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "appname",
|
||||
Position: 6,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "visible",
|
||||
},
|
||||
{
|
||||
Type: "displayName",
|
||||
Value: "Application",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "host",
|
||||
Position: 7,
|
||||
Encodings: []chronograf.ColumnEncoding{
|
||||
{
|
||||
Type: "visibility",
|
||||
Value: "visible",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
principal: oauth2.Principal{
|
||||
Organization: "default",
|
||||
Subject: "billibob",
|
||||
Issuer: "github",
|
||||
},
|
||||
},
|
||||
wants: wants{
|
||||
statusCode: 200,
|
||||
body: `
|
||||
{
|
||||
"links": {
|
||||
"self": "\/chronograf\/v1\/org_config\/logviewer"
|
||||
},
|
||||
"columns": [
|
||||
{
|
||||
"name": "time",
|
||||
"position": 0,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "hidden"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "severity",
|
||||
"position": 1,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"value": "icon"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "ruby",
|
||||
"name": "emerg"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "fire",
|
||||
"name": "alert"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "curacao",
|
||||
"name": "crit"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "tiger",
|
||||
"name": "err"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "pineapple",
|
||||
"name": "warning"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "wolf",
|
||||
"name": "notice"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "wolf",
|
||||
"name": "info"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"value": "wolf",
|
||||
"name": "debug"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "timestamp",
|
||||
"position": 3,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "message",
|
||||
"position": 2,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "facility",
|
||||
"position": 4,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "procid",
|
||||
"position": 5,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "hidden"
|
||||
},
|
||||
{
|
||||
"type": "displayName",
|
||||
"value": "ProcID!"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "appname",
|
||||
"position": 6,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
},
|
||||
{
|
||||
"type": "displayName",
|
||||
"value": "Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "host",
|
||||
"position": 7,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "GET /",
|
||||
subName: "signed into default org",
|
||||
|
@ -2717,7 +3416,8 @@ func TestServer(t *testing.T) {
|
|||
"dashboards": "/chronograf/v1/dashboards",
|
||||
"config": {
|
||||
"self": "/chronograf/v1/config",
|
||||
"auth": "/chronograf/v1/config/auth"
|
||||
"auth": "/chronograf/v1/config/auth",
|
||||
"logViewer": "/chronograf/v1/config/logviewer"
|
||||
},
|
||||
"auth": [
|
||||
{
|
||||
|
@ -2794,38 +3494,39 @@ func TestServer(t *testing.T) {
|
|||
statusCode: 200,
|
||||
body: `
|
||||
{
|
||||
"layouts": "/chronograf/v1/layouts",
|
||||
"users": "/chronograf/v1/organizations/1/users",
|
||||
"allUsers": "/chronograf/v1/users",
|
||||
"organizations": "/chronograf/v1/organizations",
|
||||
"mappings": "/chronograf/v1/mappings",
|
||||
"sources": "/chronograf/v1/sources",
|
||||
"me": "/chronograf/v1/me",
|
||||
"environment": "/chronograf/v1/env",
|
||||
"dashboards": "/chronograf/v1/dashboards",
|
||||
"config": {
|
||||
"self": "/chronograf/v1/config",
|
||||
"auth": "/chronograf/v1/config/auth"
|
||||
},
|
||||
"auth": [
|
||||
{
|
||||
"name": "github",
|
||||
"label": "Github",
|
||||
"login": "/oauth/github/login",
|
||||
"logout": "/oauth/github/logout",
|
||||
"callback": "/oauth/github/callback"
|
||||
}
|
||||
],
|
||||
"logout": "/oauth/logout",
|
||||
"external": {
|
||||
"statusFeed": ""
|
||||
},
|
||||
"flux": {
|
||||
"ast": "/chronograf/v1/flux/ast",
|
||||
"self": "/chronograf/v1/flux",
|
||||
"suggestions": "/chronograf/v1/flux/suggestions"
|
||||
}
|
||||
}
|
||||
"layouts": "/chronograf/v1/layouts",
|
||||
"users": "/chronograf/v1/organizations/1/users",
|
||||
"allUsers": "/chronograf/v1/users",
|
||||
"organizations": "/chronograf/v1/organizations",
|
||||
"mappings": "/chronograf/v1/mappings",
|
||||
"sources": "/chronograf/v1/sources",
|
||||
"me": "/chronograf/v1/me",
|
||||
"environment": "/chronograf/v1/env",
|
||||
"dashboards": "/chronograf/v1/dashboards",
|
||||
"config": {
|
||||
"self": "/chronograf/v1/config",
|
||||
"auth": "/chronograf/v1/config/auth",
|
||||
"logViewer": "/chronograf/v1/config/logviewer"
|
||||
},
|
||||
"auth": [
|
||||
{
|
||||
"name": "github",
|
||||
"label": "Github",
|
||||
"login": "/oauth/github/login",
|
||||
"logout": "/oauth/github/logout",
|
||||
"callback": "/oauth/github/callback"
|
||||
}
|
||||
],
|
||||
"logout": "/oauth/logout",
|
||||
"external": {
|
||||
"statusFeed": ""
|
||||
},
|
||||
"flux": {
|
||||
"ast": "/chronograf/v1/flux/ast",
|
||||
"self": "/chronograf/v1/flux",
|
||||
"suggestions": "/chronograf/v1/flux/suggestions"
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
)
|
||||
|
||||
var _ chronograf.OrganizationConfigStore = &OrganizationConfigStore{}
|
||||
|
||||
type OrganizationConfigStore struct {
|
||||
FindOrCreateF func(ctx context.Context, id string) (*chronograf.OrganizationConfig, error)
|
||||
PutF func(ctx context.Context, c *chronograf.OrganizationConfig) error
|
||||
}
|
||||
|
||||
func (s *OrganizationConfigStore) FindOrCreate(ctx context.Context, id string) (*chronograf.OrganizationConfig, error) {
|
||||
return s.FindOrCreateF(ctx, id)
|
||||
}
|
||||
|
||||
func (s *OrganizationConfigStore) Put(ctx context.Context, c *chronograf.OrganizationConfig) error {
|
||||
return s.PutF(ctx, c)
|
||||
}
|
|
@ -8,14 +8,15 @@ import (
|
|||
|
||||
// Store is a server.DataStore
|
||||
type Store struct {
|
||||
SourcesStore chronograf.SourcesStore
|
||||
MappingsStore chronograf.MappingsStore
|
||||
ServersStore chronograf.ServersStore
|
||||
LayoutsStore chronograf.LayoutsStore
|
||||
UsersStore chronograf.UsersStore
|
||||
DashboardsStore chronograf.DashboardsStore
|
||||
OrganizationsStore chronograf.OrganizationsStore
|
||||
ConfigStore chronograf.ConfigStore
|
||||
SourcesStore chronograf.SourcesStore
|
||||
MappingsStore chronograf.MappingsStore
|
||||
ServersStore chronograf.ServersStore
|
||||
LayoutsStore chronograf.LayoutsStore
|
||||
UsersStore chronograf.UsersStore
|
||||
DashboardsStore chronograf.DashboardsStore
|
||||
OrganizationsStore chronograf.OrganizationsStore
|
||||
ConfigStore chronograf.ConfigStore
|
||||
OrganizationConfigStore chronograf.OrganizationConfigStore
|
||||
}
|
||||
|
||||
func (s *Store) Sources(ctx context.Context) chronograf.SourcesStore {
|
||||
|
@ -48,3 +49,7 @@ func (s *Store) Dashboards(ctx context.Context) chronograf.DashboardsStore {
|
|||
func (s *Store) Config(ctx context.Context) chronograf.ConfigStore {
|
||||
return s.ConfigStore
|
||||
}
|
||||
|
||||
func (s *Store) OrganizationConfig(ctx context.Context) chronograf.OrganizationConfigStore {
|
||||
return s.OrganizationConfigStore
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package noop
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
)
|
||||
|
||||
// ensure OrganizationConfigStore implements chronograf.OrganizationConfigStore
|
||||
var _ chronograf.OrganizationConfigStore = &OrganizationConfigStore{}
|
||||
|
||||
type OrganizationConfigStore struct{}
|
||||
|
||||
func (s *OrganizationConfigStore) FindOrCreate(context.Context, string) (*chronograf.OrganizationConfig, error) {
|
||||
return nil, chronograf.ErrOrganizationConfigNotFound
|
||||
}
|
||||
|
||||
func (s *OrganizationConfigStore) Put(context.Context, *chronograf.OrganizationConfig) error {
|
||||
return fmt.Errorf("cannot replace config")
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package organizations
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
)
|
||||
|
||||
// ensure that OrganizationConfig implements chronograf.OrganizationConfigStore
|
||||
var _ chronograf.OrganizationConfigStore = &OrganizationConfigStore{}
|
||||
|
||||
// OrganizationConfigStore facade on a OrganizationConfig that filters OrganizationConfigs by organization.
|
||||
type OrganizationConfigStore struct {
|
||||
store chronograf.OrganizationConfigStore
|
||||
organization string
|
||||
}
|
||||
|
||||
// NewOrganizationConfigStore creates a new OrganizationConfigStore from an existing
|
||||
// chronograf.OrganizationConfigStore and an organization string
|
||||
func NewOrganizationConfigStore(s chronograf.OrganizationConfigStore, orgID string) *OrganizationConfigStore {
|
||||
return &OrganizationConfigStore{
|
||||
store: s,
|
||||
organization: orgID,
|
||||
}
|
||||
}
|
||||
|
||||
// FindOrCreate gets an organization's config or creates one if none exists
|
||||
func (s *OrganizationConfigStore) FindOrCreate(ctx context.Context, orgID string) (*chronograf.OrganizationConfig, error) {
|
||||
var err = validOrganization(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oc, err := s.store.FindOrCreate(ctx, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return oc, nil
|
||||
|
||||
}
|
||||
|
||||
// Put the OrganizationConfig in OrganizationConfigStore.
|
||||
func (s *OrganizationConfigStore) Put(ctx context.Context, c *chronograf.OrganizationConfig) error {
|
||||
err := validOrganization(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.store.Put(ctx, c)
|
||||
}
|
|
@ -95,13 +95,8 @@ func AuthorizedUser(
|
|||
next http.HandlerFunc,
|
||||
) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if !useAuth {
|
||||
ctx := r.Context()
|
||||
// If there is no auth, then give the user raw access to the DataStore
|
||||
r = r.WithContext(serverContext(ctx))
|
||||
next(w, r)
|
||||
return
|
||||
}
|
||||
ctx := r.Context()
|
||||
serverCtx := serverContext(ctx)
|
||||
|
||||
log := logger.
|
||||
WithField("component", "role_auth").
|
||||
|
@ -109,8 +104,24 @@ func AuthorizedUser(
|
|||
WithField("method", r.Method).
|
||||
WithField("url", r.URL)
|
||||
|
||||
ctx := r.Context()
|
||||
serverCtx := serverContext(ctx)
|
||||
defaultOrg, err := store.Organizations(serverCtx).DefaultOrganization(serverCtx)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("Failed to retrieve the default organization: %v", err))
|
||||
Error(w, http.StatusForbidden, "User is not authorized", logger)
|
||||
return
|
||||
}
|
||||
|
||||
if !useAuth {
|
||||
// If there is no auth, then set the organization id to be the default org id on context
|
||||
// so that calls like hasOrganizationContext as used in Organization Config service
|
||||
// method OrganizationConfig can successfully get the organization id
|
||||
ctx = context.WithValue(ctx, organizations.ContextKey, defaultOrg.ID)
|
||||
|
||||
// And if there is no auth, then give the user raw access to the DataStore
|
||||
r = r.WithContext(serverContext(ctx))
|
||||
next(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
p, err := getValidPrincipal(ctx)
|
||||
if err != nil {
|
||||
|
@ -127,12 +138,6 @@ func AuthorizedUser(
|
|||
|
||||
// This is as if the user was logged into the default organization
|
||||
if p.Organization == "" {
|
||||
defaultOrg, err := store.Organizations(serverCtx).DefaultOrganization(serverCtx)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("Failed to retrieve the default organization: %v", err))
|
||||
Error(w, http.StatusForbidden, "User is not authorized", logger)
|
||||
return
|
||||
}
|
||||
p.Organization = defaultOrg.ID
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ func TestAuthorizedToken(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthorizedUser(t *testing.T) {
|
||||
type fields struct {
|
||||
UsersStore chronograf.UsersStore
|
||||
|
@ -102,7 +101,7 @@ func TestAuthorizedUser(t *testing.T) {
|
|||
args: args{
|
||||
useAuth: false,
|
||||
},
|
||||
hasOrganizationContext: false,
|
||||
hasOrganizationContext: true,
|
||||
hasSuperAdminContext: false,
|
||||
hasRoleContext: false,
|
||||
hasServerContext: true,
|
||||
|
@ -1047,6 +1046,11 @@ func TestAuthorizedUser(t *testing.T) {
|
|||
Name: "The ShillBillThrilliettas",
|
||||
}, nil
|
||||
},
|
||||
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
|
||||
return &chronograf.Organization{
|
||||
ID: "0",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
Logger: clog.New(clog.DebugLevel),
|
||||
},
|
||||
|
|
|
@ -2,22 +2,26 @@ package server
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/bouk/httprouter"
|
||||
"github.com/influxdata/chronograf"
|
||||
)
|
||||
|
||||
type configLinks struct {
|
||||
Self string `json:"self"` // Self link mapping to this resource
|
||||
Auth string `json:"auth"` // Auth link to the auth config endpoint
|
||||
}
|
||||
|
||||
type configResponse struct {
|
||||
Links selfLinks `json:"links"`
|
||||
Links configLinks `json:"links"`
|
||||
chronograf.Config
|
||||
}
|
||||
|
||||
func newConfigResponse(config chronograf.Config) *configResponse {
|
||||
return &configResponse{
|
||||
Links: selfLinks{
|
||||
Links: configLinks{
|
||||
Self: "/chronograf/v1/config",
|
||||
Auth: "/chronograf/v1/config/auth",
|
||||
},
|
||||
Config: config,
|
||||
}
|
||||
|
@ -52,11 +56,12 @@ func (s *Service) Config(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
res := newConfigResponse(*config)
|
||||
|
||||
encodeJSON(w, http.StatusOK, res, s.Logger)
|
||||
}
|
||||
|
||||
// ConfigSection retrieves the section of the global application configuration
|
||||
func (s *Service) ConfigSection(w http.ResponseWriter, r *http.Request) {
|
||||
// AuthConfig retrieves the auth section of the global application configuration
|
||||
func (s *Service) AuthConfig(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
config, err := s.Store.Config(ctx).Get(ctx)
|
||||
|
@ -70,50 +75,33 @@ func (s *Service) ConfigSection(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
section := httprouter.GetParamFromContext(ctx, "section")
|
||||
var res interface{}
|
||||
switch section {
|
||||
case "auth":
|
||||
res = newAuthConfigResponse(*config)
|
||||
default:
|
||||
Error(w, http.StatusBadRequest, fmt.Sprintf("received unknown section %q", section), s.Logger)
|
||||
return
|
||||
}
|
||||
res := newAuthConfigResponse(*config)
|
||||
|
||||
encodeJSON(w, http.StatusOK, res, s.Logger)
|
||||
}
|
||||
|
||||
// ReplaceConfigSection replaces a section of the global application configuration
|
||||
func (s *Service) ReplaceConfigSection(w http.ResponseWriter, r *http.Request) {
|
||||
// ReplaceAuthConfig replaces the auth section of the global application configuration
|
||||
func (s *Service) ReplaceAuthConfig(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
var authConfig chronograf.AuthConfig
|
||||
if err := json.NewDecoder(r.Body).Decode(&authConfig); err != nil {
|
||||
invalidJSON(w, s.Logger)
|
||||
return
|
||||
}
|
||||
|
||||
config, err := s.Store.Config(ctx).Get(ctx)
|
||||
if err != nil {
|
||||
Error(w, http.StatusBadRequest, err.Error(), s.Logger)
|
||||
return
|
||||
}
|
||||
|
||||
if config == nil {
|
||||
Error(w, http.StatusBadRequest, "Configuration object was nil", s.Logger)
|
||||
return
|
||||
}
|
||||
config.Auth = authConfig
|
||||
|
||||
section := httprouter.GetParamFromContext(ctx, "section")
|
||||
var res interface{}
|
||||
switch section {
|
||||
case "auth":
|
||||
var authConfig chronograf.AuthConfig
|
||||
if err := json.NewDecoder(r.Body).Decode(&authConfig); err != nil {
|
||||
invalidJSON(w, s.Logger)
|
||||
return
|
||||
}
|
||||
config.Auth = authConfig
|
||||
res = newAuthConfigResponse(*config)
|
||||
default:
|
||||
Error(w, http.StatusBadRequest, fmt.Sprintf("received unknown section %q", section), s.Logger)
|
||||
return
|
||||
}
|
||||
|
||||
res := newAuthConfigResponse(*config)
|
||||
if err := s.Store.Config(ctx).Update(ctx, config); err != nil {
|
||||
unknownErrorWithMessage(w, err, s.Logger)
|
||||
return
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/bouk/httprouter"
|
||||
"github.com/influxdata/chronograf"
|
||||
"github.com/influxdata/chronograf/log"
|
||||
"github.com/influxdata/chronograf/mocks"
|
||||
|
@ -42,7 +41,7 @@ func TestConfig(t *testing.T) {
|
|||
wants: wants{
|
||||
statusCode: 200,
|
||||
contentType: "application/json",
|
||||
body: `{"auth": {"superAdminNewUsers": false}, "links": {"self": "/chronograf/v1/config"}}`,
|
||||
body: `{"links":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth"},"auth":{"superAdminNewUsers":false}}`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -78,13 +77,10 @@ func TestConfig(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestConfigSection(t *testing.T) {
|
||||
func TestAuthConfig(t *testing.T) {
|
||||
type fields struct {
|
||||
ConfigStore chronograf.ConfigStore
|
||||
}
|
||||
type args struct {
|
||||
section string
|
||||
}
|
||||
type wants struct {
|
||||
statusCode int
|
||||
contentType string
|
||||
|
@ -94,7 +90,6 @@ func TestConfigSection(t *testing.T) {
|
|||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wants wants
|
||||
}{
|
||||
{
|
||||
|
@ -108,35 +103,12 @@ func TestConfigSection(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
section: "auth",
|
||||
},
|
||||
wants: wants{
|
||||
statusCode: 200,
|
||||
contentType: "application/json",
|
||||
body: `{"superAdminNewUsers": false, "links": {"self": "/chronograf/v1/config/auth"}}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Get unknown configuration",
|
||||
fields: fields{
|
||||
ConfigStore: &mocks.ConfigStore{
|
||||
Config: &chronograf.Config{
|
||||
Auth: chronograf.AuthConfig{
|
||||
SuperAdminNewUsers: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
section: "unknown",
|
||||
},
|
||||
wants: wants{
|
||||
statusCode: 400,
|
||||
contentType: "application/json",
|
||||
body: `{"code":400,"message":"received unknown section \"unknown\""}`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
@ -150,16 +122,8 @@ func TestConfigSection(t *testing.T) {
|
|||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "http://any.url", nil)
|
||||
r = r.WithContext(httprouter.WithParams(
|
||||
r.Context(),
|
||||
httprouter.Params{
|
||||
{
|
||||
Key: "section",
|
||||
Value: tt.args.section,
|
||||
},
|
||||
}))
|
||||
|
||||
s.ConfigSection(w, r)
|
||||
s.AuthConfig(w, r)
|
||||
|
||||
resp := w.Result()
|
||||
content := resp.Header.Get("Content-Type")
|
||||
|
@ -178,12 +142,11 @@ func TestConfigSection(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestReplaceConfigSection(t *testing.T) {
|
||||
func TestReplaceAuthConfig(t *testing.T) {
|
||||
type fields struct {
|
||||
ConfigStore chronograf.ConfigStore
|
||||
}
|
||||
type args struct {
|
||||
section string
|
||||
payload interface{} // expects JSON serializable struct
|
||||
}
|
||||
type wants struct {
|
||||
|
@ -210,7 +173,6 @@ func TestReplaceConfigSection(t *testing.T) {
|
|||
},
|
||||
},
|
||||
args: args{
|
||||
section: "auth",
|
||||
payload: chronograf.AuthConfig{
|
||||
SuperAdminNewUsers: true,
|
||||
},
|
||||
|
@ -221,31 +183,6 @@ func TestReplaceConfigSection(t *testing.T) {
|
|||
body: `{"superAdminNewUsers": true, "links": {"self": "/chronograf/v1/config/auth"}}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Set unknown configuration",
|
||||
fields: fields{
|
||||
ConfigStore: &mocks.ConfigStore{
|
||||
Config: &chronograf.Config{
|
||||
Auth: chronograf.AuthConfig{
|
||||
SuperAdminNewUsers: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
section: "unknown",
|
||||
payload: struct {
|
||||
Data string `json:"data"`
|
||||
}{
|
||||
Data: "stuff",
|
||||
},
|
||||
},
|
||||
wants: wants{
|
||||
statusCode: 400,
|
||||
contentType: "application/json",
|
||||
body: `{"code":400,"message":"received unknown section \"unknown\""}`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
@ -259,18 +196,10 @@ func TestReplaceConfigSection(t *testing.T) {
|
|||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "http://any.url", nil)
|
||||
r = r.WithContext(httprouter.WithParams(
|
||||
r.Context(),
|
||||
httprouter.Params{
|
||||
{
|
||||
Key: "section",
|
||||
Value: tt.args.section,
|
||||
},
|
||||
}))
|
||||
buf, _ := json.Marshal(tt.args.payload)
|
||||
r.Body = ioutil.NopCloser(bytes.NewReader(buf))
|
||||
|
||||
s.ReplaceConfigSection(w, r)
|
||||
s.ReplaceAuthConfig(w, r)
|
||||
|
||||
resp := w.Result()
|
||||
content := resp.Header.Get("Content-Type")
|
||||
|
|
|
@ -12,8 +12,9 @@ type getFluxLinksResponse struct {
|
|||
}
|
||||
|
||||
type getConfigLinksResponse struct {
|
||||
Self string `json:"self"` // Location of the whole global application configuration
|
||||
Auth string `json:"auth"` // Location of the auth section of the global application configuration
|
||||
Self string `json:"self"` // Location of the whole global application configuration
|
||||
Auth string `json:"auth"` // Location of the auth section of the global application configuration
|
||||
LogViewer string `json:"logViewer"` // Location of the log viewer section of the global application configuration
|
||||
}
|
||||
|
||||
type getExternalLinksResponse struct {
|
||||
|
|
|
@ -313,8 +313,13 @@ func NewMux(opts MuxOpts, service Service) http.Handler {
|
|||
|
||||
// Global application config for Chronograf
|
||||
router.GET("/chronograf/v1/config", EnsureSuperAdmin(service.Config))
|
||||
router.GET("/chronograf/v1/config/:section", EnsureSuperAdmin(service.ConfigSection))
|
||||
router.PUT("/chronograf/v1/config/:section", EnsureSuperAdmin(service.ReplaceConfigSection))
|
||||
router.GET("/chronograf/v1/config/auth", EnsureSuperAdmin(service.AuthConfig))
|
||||
router.PUT("/chronograf/v1/config/auth", EnsureSuperAdmin(service.ReplaceAuthConfig))
|
||||
|
||||
// Organization config settings for Chronograf
|
||||
router.GET("/chronograf/v1/org_config", EnsureViewer(service.OrganizationConfig))
|
||||
router.GET("/chronograf/v1/org_config/logviewer", EnsureViewer(service.OrganizationLogViewerConfig))
|
||||
router.PUT("/chronograf/v1/org_config/logviewer", EnsureEditor(service.ReplaceOrganizationLogViewerConfig))
|
||||
|
||||
router.GET("/chronograf/v1/env", EnsureViewer(service.Environment))
|
||||
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
)
|
||||
|
||||
type organizationConfigLinks struct {
|
||||
Self string `json:"self"` // Self link mapping to this resource
|
||||
LogViewer string `json:"logViewer"` // LogViewer link to the organization log viewer config endpoint
|
||||
}
|
||||
|
||||
type organizationConfigResponse struct {
|
||||
Links organizationConfigLinks `json:"links"`
|
||||
chronograf.OrganizationConfig
|
||||
}
|
||||
|
||||
func newOrganizationConfigResponse(c chronograf.OrganizationConfig) *organizationConfigResponse {
|
||||
return &organizationConfigResponse{
|
||||
Links: organizationConfigLinks{
|
||||
Self: "/chronograf/v1/org_config",
|
||||
LogViewer: "/chronograf/v1/org_config/logviewer",
|
||||
},
|
||||
OrganizationConfig: c,
|
||||
}
|
||||
}
|
||||
|
||||
type logViewerConfigResponse struct {
|
||||
Links selfLinks `json:"links"`
|
||||
chronograf.LogViewerConfig
|
||||
}
|
||||
|
||||
func newLogViewerConfigResponse(c chronograf.LogViewerConfig) *logViewerConfigResponse {
|
||||
return &logViewerConfigResponse{
|
||||
Links: selfLinks{
|
||||
Self: "/chronograf/v1/org_config/logviewer",
|
||||
},
|
||||
LogViewerConfig: c,
|
||||
}
|
||||
}
|
||||
|
||||
// OrganizationConfig retrieves the organization-wide config settings
|
||||
func (s *Service) OrganizationConfig(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
orgID, ok := hasOrganizationContext(ctx)
|
||||
if !ok {
|
||||
Error(w, http.StatusBadRequest, "Organization not found on context", s.Logger)
|
||||
return
|
||||
}
|
||||
|
||||
config, err := s.Store.OrganizationConfig(ctx).FindOrCreate(ctx, orgID)
|
||||
if err != nil {
|
||||
Error(w, http.StatusBadRequest, err.Error(), s.Logger)
|
||||
return
|
||||
}
|
||||
|
||||
res := newOrganizationConfigResponse(*config)
|
||||
encodeJSON(w, http.StatusOK, res, s.Logger)
|
||||
}
|
||||
|
||||
// OrganizationLogViewerConfig retrieves the log viewer UI section of the organization config
|
||||
// This uses a FindOrCreate function to ensure that any new organizations have
|
||||
// default organization config values, without having to associate organization creation with
|
||||
// organization config creation.
|
||||
func (s *Service) OrganizationLogViewerConfig(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
orgID, ok := hasOrganizationContext(ctx)
|
||||
if !ok {
|
||||
Error(w, http.StatusBadRequest, "Organization not found on context", s.Logger)
|
||||
return
|
||||
}
|
||||
|
||||
config, err := s.Store.OrganizationConfig(ctx).FindOrCreate(ctx, orgID)
|
||||
if err != nil {
|
||||
Error(w, http.StatusBadRequest, err.Error(), s.Logger)
|
||||
return
|
||||
}
|
||||
|
||||
res := newLogViewerConfigResponse(config.LogViewer)
|
||||
encodeJSON(w, http.StatusOK, res, s.Logger)
|
||||
}
|
||||
|
||||
// ReplaceOrganizationLogViewerConfig replaces the log viewer UI section of the organization config
|
||||
func (s *Service) ReplaceOrganizationLogViewerConfig(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
orgID, ok := hasOrganizationContext(ctx)
|
||||
if !ok {
|
||||
Error(w, http.StatusBadRequest, "Organization not found on context", s.Logger)
|
||||
return
|
||||
}
|
||||
|
||||
var logViewerConfig chronograf.LogViewerConfig
|
||||
if err := json.NewDecoder(r.Body).Decode(&logViewerConfig); err != nil {
|
||||
invalidJSON(w, s.Logger)
|
||||
return
|
||||
}
|
||||
if err := validLogViewerConfig(logViewerConfig); err != nil {
|
||||
Error(w, http.StatusBadRequest, err.Error(), s.Logger)
|
||||
return
|
||||
}
|
||||
|
||||
config, err := s.Store.OrganizationConfig(ctx).FindOrCreate(ctx, orgID)
|
||||
if err != nil {
|
||||
Error(w, http.StatusBadRequest, err.Error(), s.Logger)
|
||||
return
|
||||
}
|
||||
config.LogViewer = logViewerConfig
|
||||
if err := s.Store.OrganizationConfig(ctx).Put(ctx, config); err != nil {
|
||||
unknownErrorWithMessage(w, err, s.Logger)
|
||||
return
|
||||
}
|
||||
|
||||
res := newLogViewerConfigResponse(config.LogViewer)
|
||||
encodeJSON(w, http.StatusOK, res, s.Logger)
|
||||
}
|
||||
|
||||
// validLogViewerConfig ensures that the request body log viewer UI config is valid
|
||||
// to be valid, it must: not be empty, have at least one column, not have multiple
|
||||
// columns with the same name or position value, each column must have a visbility
|
||||
// of either "visible" or "hidden" and if a column is of type severity, it must have
|
||||
// at least one severity format of type icon, text, or both
|
||||
func validLogViewerConfig(c chronograf.LogViewerConfig) error {
|
||||
if len(c.Columns) == 0 {
|
||||
return fmt.Errorf("Invalid log viewer config: must have at least 1 column")
|
||||
}
|
||||
|
||||
nameMatcher := map[string]bool{}
|
||||
positionMatcher := map[int32]bool{}
|
||||
|
||||
for _, clm := range c.Columns {
|
||||
iconCount := 0
|
||||
textCount := 0
|
||||
visibility := 0
|
||||
|
||||
// check that each column has a unique value for the name and position properties
|
||||
if _, ok := nameMatcher[clm.Name]; ok {
|
||||
return fmt.Errorf("Invalid log viewer config: Duplicate column name %s", clm.Name)
|
||||
}
|
||||
nameMatcher[clm.Name] = true
|
||||
if _, ok := positionMatcher[clm.Position]; ok {
|
||||
return fmt.Errorf("Invalid log viewer config: Multiple columns with same position value")
|
||||
}
|
||||
positionMatcher[clm.Position] = true
|
||||
|
||||
for _, e := range clm.Encodings {
|
||||
if e.Type == "visibility" {
|
||||
visibility++
|
||||
if !(e.Value == "visible" || e.Value == "hidden") {
|
||||
return fmt.Errorf("Invalid log viewer config: invalid visibility in column %s", clm.Name)
|
||||
}
|
||||
}
|
||||
|
||||
if clm.Name == "severity" {
|
||||
if e.Value == "icon" {
|
||||
iconCount++
|
||||
} else if e.Value == "text" {
|
||||
textCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if visibility != 1 {
|
||||
return fmt.Errorf("Invalid log viewer config: missing visibility encoding in column %s", clm.Name)
|
||||
}
|
||||
|
||||
if clm.Name == "severity" {
|
||||
if iconCount+textCount == 0 || iconCount > 1 || textCount > 1 {
|
||||
return fmt.Errorf("Invalid log viewer config: invalid number of severity format encodings in column %s", clm.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -87,8 +87,9 @@ func (a *AllRoutes) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
Mappings: "/chronograf/v1/mappings",
|
||||
Dashboards: "/chronograf/v1/dashboards",
|
||||
Config: getConfigLinksResponse{
|
||||
Self: "/chronograf/v1/config",
|
||||
Auth: "/chronograf/v1/config/auth",
|
||||
Self: "/chronograf/v1/config",
|
||||
Auth: "/chronograf/v1/config/auth",
|
||||
LogViewer: "/chronograf/v1/config/logviewer",
|
||||
},
|
||||
Auth: make([]AuthRoute, len(a.AuthRoutes)), // We want to return at least an empty array, rather than null
|
||||
ExternalLinks: getExternalLinksResponse{
|
||||
|
|
|
@ -29,7 +29,7 @@ func TestAllRoutes(t *testing.T) {
|
|||
if err := json.Unmarshal(body, &routes); err != nil {
|
||||
t.Error("TestAllRoutes not able to unmarshal JSON response")
|
||||
}
|
||||
want := `{"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/organizations/default/users","allUsers":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","environment":"/chronograf/v1/env","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth"},"auth":[],"external":{"statusFeed":""},"flux":{"ast":"/chronograf/v1/flux/ast","self":"/chronograf/v1/flux","suggestions":"/chronograf/v1/flux/suggestions"}}
|
||||
want := `{"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/organizations/default/users","allUsers":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","environment":"/chronograf/v1/env","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth","logViewer":"/chronograf/v1/config/logviewer"},"auth":[],"external":{"statusFeed":""},"flux":{"ast":"/chronograf/v1/flux/ast","self":"/chronograf/v1/flux","suggestions":"/chronograf/v1/flux/suggestions"}}
|
||||
`
|
||||
if want != string(body) {
|
||||
t.Errorf("TestAllRoutes\nwanted\n*%s*\ngot\n*%s*", want, string(body))
|
||||
|
@ -67,7 +67,7 @@ func TestAllRoutesWithAuth(t *testing.T) {
|
|||
if err := json.Unmarshal(body, &routes); err != nil {
|
||||
t.Error("TestAllRoutesWithAuth not able to unmarshal JSON response")
|
||||
}
|
||||
want := `{"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/organizations/default/users","allUsers":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","environment":"/chronograf/v1/env","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth"},"auth":[{"name":"github","label":"GitHub","login":"/oauth/github/login","logout":"/oauth/github/logout","callback":"/oauth/github/callback"}],"logout":"/oauth/logout","external":{"statusFeed":""},"flux":{"ast":"/chronograf/v1/flux/ast","self":"/chronograf/v1/flux","suggestions":"/chronograf/v1/flux/suggestions"}}
|
||||
want := `{"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/organizations/default/users","allUsers":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","environment":"/chronograf/v1/env","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth","logViewer":"/chronograf/v1/config/logviewer"},"auth":[{"name":"github","label":"GitHub","login":"/oauth/github/login","logout":"/oauth/github/logout","callback":"/oauth/github/callback"}],"logout":"/oauth/logout","external":{"statusFeed":""},"flux":{"ast":"/chronograf/v1/flux/ast","self":"/chronograf/v1/flux","suggestions":"/chronograf/v1/flux/suggestions"}}
|
||||
`
|
||||
if want != string(body) {
|
||||
t.Errorf("TestAllRoutesWithAuth\nwanted\n*%s*\ngot\n*%s*", want, string(body))
|
||||
|
@ -100,7 +100,7 @@ func TestAllRoutesWithExternalLinks(t *testing.T) {
|
|||
if err := json.Unmarshal(body, &routes); err != nil {
|
||||
t.Error("TestAllRoutesWithExternalLinks not able to unmarshal JSON response")
|
||||
}
|
||||
want := `{"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/organizations/default/users","allUsers":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","environment":"/chronograf/v1/env","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth"},"auth":[],"external":{"statusFeed":"http://pineapple.life/feed.json","custom":[{"name":"cubeapple","url":"https://cube.apple"}]},"flux":{"ast":"/chronograf/v1/flux/ast","self":"/chronograf/v1/flux","suggestions":"/chronograf/v1/flux/suggestions"}}
|
||||
want := `{"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/organizations/default/users","allUsers":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","environment":"/chronograf/v1/env","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth","logViewer":"/chronograf/v1/config/logviewer"},"auth":[],"external":{"statusFeed":"http://pineapple.life/feed.json","custom":[{"name":"cubeapple","url":"https://cube.apple"}]},"flux":{"ast":"/chronograf/v1/flux/ast","self":"/chronograf/v1/flux","suggestions":"/chronograf/v1/flux/suggestions"}}
|
||||
`
|
||||
if want != string(body) {
|
||||
t.Errorf("TestAllRoutesWithExternalLinks\nwanted\n*%s*\ngot\n*%s*", want, string(body))
|
||||
|
|
|
@ -486,14 +486,15 @@ func openService(ctx context.Context, buildInfo chronograf.BuildInfo, boltPath s
|
|||
return Service{
|
||||
TimeSeriesClient: &InfluxClient{},
|
||||
Store: &Store{
|
||||
LayoutsStore: layouts,
|
||||
DashboardsStore: dashboards,
|
||||
SourcesStore: sources,
|
||||
ServersStore: kapacitors,
|
||||
OrganizationsStore: organizations,
|
||||
UsersStore: db.UsersStore,
|
||||
ConfigStore: db.ConfigStore,
|
||||
MappingsStore: db.MappingsStore,
|
||||
LayoutsStore: layouts,
|
||||
DashboardsStore: dashboards,
|
||||
SourcesStore: sources,
|
||||
ServersStore: kapacitors,
|
||||
OrganizationsStore: organizations,
|
||||
UsersStore: db.UsersStore,
|
||||
ConfigStore: db.ConfigStore,
|
||||
MappingsStore: db.MappingsStore,
|
||||
OrganizationConfigStore: db.OrganizationConfigStore,
|
||||
},
|
||||
Logger: logger,
|
||||
UseAuth: useAuth,
|
||||
|
|
|
@ -91,6 +91,7 @@ type DataStore interface {
|
|||
Mappings(ctx context.Context) chronograf.MappingsStore
|
||||
Dashboards(ctx context.Context) chronograf.DashboardsStore
|
||||
Config(ctx context.Context) chronograf.ConfigStore
|
||||
OrganizationConfig(ctx context.Context) chronograf.OrganizationConfigStore
|
||||
}
|
||||
|
||||
// ensure that Store implements a DataStore
|
||||
|
@ -98,18 +99,19 @@ var _ DataStore = &Store{}
|
|||
|
||||
// Store implements the DataStore interface
|
||||
type Store struct {
|
||||
SourcesStore chronograf.SourcesStore
|
||||
ServersStore chronograf.ServersStore
|
||||
LayoutsStore chronograf.LayoutsStore
|
||||
UsersStore chronograf.UsersStore
|
||||
DashboardsStore chronograf.DashboardsStore
|
||||
MappingsStore chronograf.MappingsStore
|
||||
OrganizationsStore chronograf.OrganizationsStore
|
||||
ConfigStore chronograf.ConfigStore
|
||||
SourcesStore chronograf.SourcesStore
|
||||
ServersStore chronograf.ServersStore
|
||||
LayoutsStore chronograf.LayoutsStore
|
||||
UsersStore chronograf.UsersStore
|
||||
DashboardsStore chronograf.DashboardsStore
|
||||
MappingsStore chronograf.MappingsStore
|
||||
OrganizationsStore chronograf.OrganizationsStore
|
||||
ConfigStore chronograf.ConfigStore
|
||||
OrganizationConfigStore chronograf.OrganizationConfigStore
|
||||
}
|
||||
|
||||
// Sources returns a noop.SourcesStore if the context has no organization specified
|
||||
// and a organization.SourcesStore otherwise.
|
||||
// and an organization.SourcesStore otherwise.
|
||||
func (s *Store) Sources(ctx context.Context) chronograf.SourcesStore {
|
||||
if isServer := hasServerContext(ctx); isServer {
|
||||
return s.SourcesStore
|
||||
|
@ -122,7 +124,7 @@ func (s *Store) Sources(ctx context.Context) chronograf.SourcesStore {
|
|||
}
|
||||
|
||||
// Servers returns a noop.ServersStore if the context has no organization specified
|
||||
// and a organization.ServersStore otherwise.
|
||||
// and an organization.ServersStore otherwise.
|
||||
func (s *Store) Servers(ctx context.Context) chronograf.ServersStore {
|
||||
if isServer := hasServerContext(ctx); isServer {
|
||||
return s.ServersStore
|
||||
|
@ -157,7 +159,7 @@ func (s *Store) Users(ctx context.Context) chronograf.UsersStore {
|
|||
}
|
||||
|
||||
// Dashboards returns a noop.DashboardsStore if the context has no organization specified
|
||||
// and a organization.DashboardsStore otherwise.
|
||||
// and an organization.DashboardsStore otherwise.
|
||||
func (s *Store) Dashboards(ctx context.Context) chronograf.DashboardsStore {
|
||||
if isServer := hasServerContext(ctx); isServer {
|
||||
return s.DashboardsStore
|
||||
|
@ -169,6 +171,16 @@ func (s *Store) Dashboards(ctx context.Context) chronograf.DashboardsStore {
|
|||
return &noop.DashboardsStore{}
|
||||
}
|
||||
|
||||
// OrganizationConfig returns a noop.OrganizationConfigStore if the context has no organization specified
|
||||
// and an organization.OrganizationConfigStore otherwise.
|
||||
func (s *Store) OrganizationConfig(ctx context.Context) chronograf.OrganizationConfigStore {
|
||||
if orgID, ok := hasOrganizationContext(ctx); ok {
|
||||
return organizations.NewOrganizationConfigStore(s.OrganizationConfigStore, orgID)
|
||||
}
|
||||
|
||||
return &noop.OrganizationConfigStore{}
|
||||
}
|
||||
|
||||
// Organizations returns the underlying OrganizationsStore.
|
||||
func (s *Store) Organizations(ctx context.Context) chronograf.OrganizationsStore {
|
||||
if isServer := hasServerContext(ctx); isServer {
|
||||
|
@ -191,6 +203,7 @@ func (s *Store) Config(ctx context.Context) chronograf.ConfigStore {
|
|||
if isSuperAdmin := hasSuperAdminContext(ctx); isSuperAdmin {
|
||||
return s.ConfigStore
|
||||
}
|
||||
|
||||
return &noop.ConfigStore{}
|
||||
}
|
||||
|
||||
|
|
|
@ -2865,27 +2865,47 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/chronograf/v1/config/:section": {
|
||||
"/chronograf/v1/config": {
|
||||
"get": {
|
||||
"tags": ["config"],
|
||||
"summary": "Returns the settings for a specific section of the app",
|
||||
"description": "All settings for a specific section of the app",
|
||||
"summary": "Returns the global application configuration",
|
||||
"description": "All global application configurations",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Returns an object with the settings for a section of the app",
|
||||
"description": "Returns an object with the global configurations",
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/LogViewerUIConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/AuthConfig"
|
||||
}
|
||||
]
|
||||
"$ref": "#/definitions/Config"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Could not find requested section",
|
||||
"description": "Could not find global application config",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Unexpected internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/chronograf/v1/config/auth": {
|
||||
"get": {
|
||||
"tags": ["config"],
|
||||
"summary": "Returns the global application configuration for auth",
|
||||
"description": "All global application configuration for auth",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Returns an object with the global application configuration for auth",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AuthConfig"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Could not find auth configuration",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
|
@ -2900,49 +2920,120 @@
|
|||
},
|
||||
"put": {
|
||||
"tags": ["config"],
|
||||
"summary": "Updates the settings for a specific section of the app",
|
||||
"description": "Updates settings for a specific section of the app",
|
||||
"summary": "Updates the global application configuration for auth",
|
||||
"description": "Replaces the global application configuration for auth",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "section",
|
||||
"in": "path",
|
||||
"type": "string",
|
||||
"description": "Section name for the target section settings",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"enum": ["logViewer", "auth"]
|
||||
},
|
||||
"name": "auth",
|
||||
"in": "body",
|
||||
"description":
|
||||
"Section configuration update parameters",
|
||||
"Auth configuration update object",
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/LogViewerUIConfig"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/AuthConfig"
|
||||
}
|
||||
]
|
||||
"$ref": "#/definitions/AuthConfig"
|
||||
},
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Returns an object with the updated UI settings for a specific section",
|
||||
"description": "Returns an object with the updated auth configuration",
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/LogViewerUIConfig"
|
||||
}
|
||||
]
|
||||
"$ref": "#/definitions/AuthConfig"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Could not find requested section",
|
||||
"description": "Could not find auth configuration",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Unexpected internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/chronograf/v1/org_config": {
|
||||
"get": {
|
||||
"tags": ["organization config"],
|
||||
"summary": "Retrieve the organization configuration",
|
||||
"description": "Organization-specific configurations such as log viewer configs",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Returns an object with the organization-specific configurations",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/OrganizationConfig"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Could not find organization config",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Unexpected internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/chronograf/v1/org_config/logviewer": {
|
||||
"get": {
|
||||
"tags": ["organization config"],
|
||||
"summary": "Retrieve the organization-specific log viewer configurations",
|
||||
"description": "Retrieve the log viewer configurations for the user's current organization",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Returns an log viewer configuration object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/LogViewerConfig"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Could not find the log viewer configuration for this organization",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Unexpected internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"tags": ["organization config"],
|
||||
"summary": "Update the log viewer configuration",
|
||||
"description": "Update the log viewer configuration for a specific organization",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "logViewer",
|
||||
"in": "body",
|
||||
"description":
|
||||
"Log Viewer configuration update object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/LogViewerConfig"
|
||||
},
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Returns an object with the updated log viewer configurations",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/LogViewerConfig"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Could not find log viewer configurations for the specified organization",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Error"
|
||||
}
|
||||
|
@ -5144,79 +5235,99 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"LogViewerUIColumn": {
|
||||
"description": "Contains the settings for the log viewer page UI",
|
||||
"Config": {
|
||||
"description": "Global application configuration",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"encoding",
|
||||
"position"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "Unique identifier name of the column",
|
||||
"type": "string"
|
||||
},
|
||||
"position": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"encoding": {
|
||||
"description": "Composable encoding options for the column",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description":"Type and value and optional name of an encoding",
|
||||
"type": "object",
|
||||
"required": ["type", "value"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
"auth": {
|
||||
"$ref": "#/definitions/AuthConfig"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"name": "severity",
|
||||
"position": 0,
|
||||
"encoding": [
|
||||
{
|
||||
"type": "label",
|
||||
"value": "icon"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"value": "text"
|
||||
},
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"name": "ruby",
|
||||
"value": "emergency"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"name": "rainforest",
|
||||
"value": "info"
|
||||
},
|
||||
{
|
||||
"type": "displayName",
|
||||
"value": "Log Severity!"
|
||||
}
|
||||
]
|
||||
"auth": {
|
||||
"superAdminNewUsers": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"LogViewerUIConfig": {
|
||||
"description": "Contains the settings for the log viewer page UI",
|
||||
"AuthConfig": {
|
||||
"description": "Global application configuration for auth",
|
||||
"type": "object",
|
||||
"required": ["superAdminNewUsers"],
|
||||
"properties": {
|
||||
"superAdminNewUsers": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"superAdminNewUsers": true
|
||||
}
|
||||
},
|
||||
"OrganizationConfig": {
|
||||
"description": "Configurations for a specific organization",
|
||||
"type": "object",
|
||||
"required": ["logViewer"],
|
||||
"properties": {
|
||||
"organization": {
|
||||
"type": "string",
|
||||
"readOnly": true
|
||||
},
|
||||
"logViewer": {
|
||||
"$ref": "#/definitions/LogViewerConfig"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"organization": "default",
|
||||
"logViewer": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "severity",
|
||||
"position": 0,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "label",
|
||||
"value": "icon"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"value": "text"
|
||||
},
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"name": "ruby",
|
||||
"value": "emergency"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"name": "rainforest",
|
||||
"value": "info"
|
||||
},
|
||||
{
|
||||
"type": "displayName",
|
||||
"value": "Log Severity!"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "messages",
|
||||
"position": 1,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "hidden"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"LogViewerConfig": {
|
||||
"description": "Contains the organization-specific configuration for the log viewer",
|
||||
"type": "object",
|
||||
"required": ["columns"],
|
||||
"properties": {
|
||||
|
@ -5224,7 +5335,7 @@
|
|||
"description": "Defines the order, names, and visibility of columns in the log viewer table",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/LogViewerUIColumn"
|
||||
"$ref": "#/definitions/LogViewerColumn"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -5233,7 +5344,7 @@
|
|||
{
|
||||
"name": "severity",
|
||||
"position": 0,
|
||||
"encoding": [
|
||||
"encodings": [
|
||||
{
|
||||
"type": "label",
|
||||
"value": "icon"
|
||||
|
@ -5265,7 +5376,7 @@
|
|||
{
|
||||
"name": "messages",
|
||||
"position": 1,
|
||||
"encoding": [
|
||||
"encodings": [
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "hidden"
|
||||
|
@ -5275,15 +5386,76 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"AuthConfig": {
|
||||
"LogViewerColumn": {
|
||||
"description": "Contains the organization-specific configuration for the log viewer",
|
||||
"type": "object",
|
||||
"required": ["superAdminNewUsers"],
|
||||
"required": [
|
||||
"name",
|
||||
"encodings",
|
||||
"position"
|
||||
],
|
||||
"properties": {
|
||||
"superAdminNewUsers": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
"name": {
|
||||
"description": "Unique identifier name of the column",
|
||||
"type": "string"
|
||||
},
|
||||
"position": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"encodings": {
|
||||
"description": "Composable encoding options for the column",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description":"Type and value and optional name of an encoding",
|
||||
"type": "object",
|
||||
"required": ["type", "value"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"name": "severity",
|
||||
"position": 0,
|
||||
"encodings": [
|
||||
{
|
||||
"type": "label",
|
||||
"value": "icon"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"value": "text"
|
||||
},
|
||||
{
|
||||
"type": "visibility",
|
||||
"value": "visible"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"name": "ruby",
|
||||
"value": "emergency"
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"name": "rainforest",
|
||||
"value": "info"
|
||||
},
|
||||
{
|
||||
"type": "displayName",
|
||||
"value": "Log Severity!"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Routes": {
|
||||
"type": "object",
|
||||
|
|
|
@ -174,10 +174,13 @@ class DragAndDrop extends PureComponent<Props, State> {
|
|||
const reader = new FileReader()
|
||||
reader.readAsText(file)
|
||||
reader.onload = loadEvent => {
|
||||
this.setState({
|
||||
uploadContent: loadEvent.target.result,
|
||||
fileName: file.name,
|
||||
})
|
||||
this.setState(
|
||||
{
|
||||
uploadContent: loadEvent.target.result,
|
||||
fileName: file.name,
|
||||
},
|
||||
this.handleSubmit
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ class MapTemplateBuilder extends PureComponent<TemplateBuilderProps, State> {
|
|||
public render() {
|
||||
const {onUpdateDefaultTemplateValue, template} = this.props
|
||||
const {templateValuesString} = this.state
|
||||
const pluralizer = template.values.length === 1 ? '' : 's'
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -65,7 +64,7 @@ class MapTemplateBuilder extends PureComponent<TemplateBuilderProps, State> {
|
|||
<div className="form-group col-xs-12 temp-builder--results">
|
||||
<p className="temp-builder--validation">
|
||||
Mapping contains <strong>{template.values.length}</strong> key-value
|
||||
pair{pluralizer}
|
||||
pair{this.pluralizer}
|
||||
</p>
|
||||
{template.values.length > 0 && (
|
||||
<TemplatePreviewList
|
||||
|
@ -78,6 +77,10 @@ class MapTemplateBuilder extends PureComponent<TemplateBuilderProps, State> {
|
|||
)
|
||||
}
|
||||
|
||||
private get pluralizer(): string {
|
||||
return this.props.template.values.length === 1 ? '' : 's'
|
||||
}
|
||||
|
||||
private handleUploadFile = (
|
||||
uploadContent: string,
|
||||
fileName: string
|
||||
|
@ -114,9 +117,10 @@ class MapTemplateBuilder extends PureComponent<TemplateBuilderProps, State> {
|
|||
this.setState({templateValuesString: e.target.value})
|
||||
}
|
||||
|
||||
private constructValuesFromString(templateValuesString) {
|
||||
private constructValuesFromString(templateValuesString: string) {
|
||||
const {notify} = this.props
|
||||
const parsedTVS = Papa.parse(templateValuesString)
|
||||
const trimmed = _.trimEnd(templateValuesString, '\n')
|
||||
const parsedTVS = Papa.parse(trimmed)
|
||||
const templateValuesData = getDeep<string[][]>(parsedTVS, 'data', [[]])
|
||||
|
||||
if (templateValuesData.length === 0) {
|
||||
|
|
|
@ -42,7 +42,7 @@ class TemplatePreviewListItem extends PureComponent<Props> {
|
|||
private get mapTempVarKey(): string {
|
||||
const {item} = this.props
|
||||
if (item.type === TemplateValueType.Map) {
|
||||
return `${item.key} -->`
|
||||
return `${item.key} --> `
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue