From de348f26725fb54011f224d4c20b7f94d9ca9926 Mon Sep 17 00:00:00 2001 From: Mahan Zendedel DH Date: Thu, 30 May 2024 17:31:59 +0400 Subject: [PATCH] feat: add plugin custom charts (#169) * feat: add plugin custom charts * fix: overview chart replacement problem --- cmd/root.go | 40 +- controller/optimization.go | 47 +- pkg/plugin/manager.go | 32 +- pkg/plugin/proto/plugin.proto | 40 + pkg/plugin/proto/src/golang/plugin.pb.go | 1061 +++++++++++++---- pkg/plugin/proto/src/golang/plugin_grpc.pb.go | 10 +- view/app.go | 21 +- view/page_overview.go | 8 +- view/page_overview_plugin_custom.go | 188 +++ view/page_preferences.go | 95 +- view/page_resource_details.go | 8 +- view/page_resource_details_plugin_custom.go | 257 ++++ 12 files changed, 1483 insertions(+), 324 deletions(-) create mode 100644 view/page_overview_plugin_custom.go create mode 100644 view/page_resource_details_plugin_custom.go diff --git a/cmd/root.go b/cmd/root.go index e6b6b13..115cd3b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -243,19 +243,33 @@ func Execute() { statusBar := view.NewStatusBarView(jobsController, helpController) jobsPage := view.NewJobsPage(jobsController, helpController, statusBar) - optimizationsController := controller.NewOptimizations() - optimizationsPage := view.NewOptimizationsView(optimizationsController, helpController, statusBar) - optimizationsDetailsPage := view.NewOptimizationDetailsView(optimizationsController, helpController, statusBar) - preferencesPage := view.NewPreferencesConfiguration(helpController, optimizationsController, statusBar) - - manager.SetUI(jobsController, optimizationsController) - - p := tea.NewProgram(view.NewApp( - optimizationsPage, - optimizationsDetailsPage, - preferencesPage, - jobsPage, - ), tea.WithFPS(10)) + var app *view.App + if runningPlg.Plugin.Config.DevicesChart != nil && runningPlg.Plugin.Config.OverviewChart != nil { + optimizationsController := controller.NewOptimizations[golang.ChartOptimizationItem]() + optimizationsPage := view.NewPluginCustomOverviewPageView(runningPlg.Plugin.Config.OverviewChart, optimizationsController, helpController, statusBar) + optimizationsDetailsPage := view.NewPluginCustomOptimizationDetailsView(runningPlg.Plugin.Config.DevicesChart, optimizationsController, helpController, statusBar) + preferencesPage := view.NewPreferencesConfiguration(helpController, optimizationsController, statusBar) + manager.SetCustomUI(jobsController, optimizationsController) + app = view.NewCustomPluginApp( + optimizationsPage, + optimizationsDetailsPage, + preferencesPage, + jobsPage, + ) + } else { + optimizationsController := controller.NewOptimizations[golang.OptimizationItem]() + optimizationsPage := view.NewOptimizationsView(optimizationsController, helpController, statusBar) + optimizationsDetailsPage := view.NewOptimizationDetailsView(optimizationsController, helpController, statusBar) + preferencesPage := view.NewPreferencesConfiguration(helpController, optimizationsController, statusBar) + manager.SetDefaultUI(jobsController, optimizationsController) + app = view.NewApp( + optimizationsPage, + optimizationsDetailsPage, + preferencesPage, + jobsPage, + ) + } + p := tea.NewProgram(app, tea.WithFPS(10)) if _, err := p.Run(); err != nil { return err } diff --git a/controller/optimization.go b/controller/optimization.go index 45eac07..851d003 100644 --- a/controller/optimization.go +++ b/controller/optimization.go @@ -4,31 +4,42 @@ import ( "github.com/kaytu-io/kaytu/pkg/plugin/proto/src/golang" ) -type Optimizations struct { - itemsChan chan *golang.OptimizationItem - items []*golang.OptimizationItem +type Optimizations[T golang.OptimizationItem | golang.ChartOptimizationItem] struct { + itemsChan chan *T + items []*T - selectedItem *golang.OptimizationItem + selectedItem *T reEvaluateFunc func(id string, items []*golang.PreferenceItem) } -func NewOptimizations() *Optimizations { - o := Optimizations{ - itemsChan: make(chan *golang.OptimizationItem, 1000), +func NewOptimizations[T golang.OptimizationItem | golang.ChartOptimizationItem]() *Optimizations[T] { + o := Optimizations[T]{ + itemsChan: make(chan *T, 1000), } go o.Process() return &o } -func (o *Optimizations) Process() { +func (o *Optimizations[T]) Process() { for newItem := range o.itemsChan { updated := false for idx, i := range o.items { - if newItem.Id == i.Id { - o.items[idx] = newItem - updated = true - break + switch castedNewItem := any(newItem).(type) { + case *golang.OptimizationItem: + castedI := any(i).(*golang.OptimizationItem) + if castedNewItem.Id == castedI.Id { + o.items[idx] = newItem + updated = true + break + } + case *golang.ChartOptimizationItem: + castedI := any(i).(*golang.ChartOptimizationItem) + if castedNewItem.GetOverviewChartRow().GetRowId() == castedI.GetOverviewChartRow().GetRowId() { + o.items[idx] = newItem + updated = true + break + } } } if !updated { @@ -37,26 +48,26 @@ func (o *Optimizations) Process() { } } -func (o *Optimizations) SendItem(item *golang.OptimizationItem) { +func (o *Optimizations[T]) SendItem(item *T) { o.itemsChan <- item } -func (o *Optimizations) Items() []*golang.OptimizationItem { +func (o *Optimizations[T]) Items() []*T { return o.items } -func (o *Optimizations) SetReEvaluateFunc(f func(id string, items []*golang.PreferenceItem)) { +func (o *Optimizations[T]) SetReEvaluateFunc(f func(id string, items []*golang.PreferenceItem)) { o.reEvaluateFunc = f } -func (o *Optimizations) SelectItem(i *golang.OptimizationItem) { +func (o *Optimizations[T]) SelectItem(i *T) { o.selectedItem = i } -func (o *Optimizations) SelectedItem() *golang.OptimizationItem { +func (o *Optimizations[T]) SelectedItem() *T { return o.selectedItem } -func (o *Optimizations) ReEvaluate(id string, preferences []*golang.PreferenceItem) { +func (o *Optimizations[T]) ReEvaluate(id string, preferences []*golang.PreferenceItem) { o.reEvaluateFunc(id, preferences) } diff --git a/pkg/plugin/manager.go b/pkg/plugin/manager.go index 7636ab5..0f03722 100644 --- a/pkg/plugin/manager.go +++ b/pkg/plugin/manager.go @@ -39,8 +39,9 @@ type Manager struct { golang.PluginServer - jobs *controller.Jobs - optimizations *controller.Optimizations + jobs *controller.Jobs + optimizations *controller.Optimizations[golang.OptimizationItem] + pluginCustomOptimizations *controller.Optimizations[golang.ChartOptimizationItem] NonInteractiveView *view.NonInteractiveView } @@ -147,8 +148,17 @@ func (m *Manager) Register(stream golang.Plugin_RegisterServer) error { m.jobs.Publish(receivedMsg.GetJob()) case receivedMsg.GetOi() != nil: + if m.optimizations == nil { + return errors.New("default optimizations controller not set - is plugin running in custom ui mode?") + } m.optimizations.SendItem(receivedMsg.GetOi()) + case receivedMsg.GetCoi() != nil: + if m.pluginCustomOptimizations == nil { + return errors.New("custom optimizations controller not set - is plugin running in default ui mode?") + } + m.pluginCustomOptimizations.SendItem(receivedMsg.GetCoi()) + case receivedMsg.GetErr() != nil: m.jobs.PublishError(fmt.Errorf(receivedMsg.GetErr().Error)) } @@ -301,7 +311,7 @@ func (m *Manager) Install(addr, token string, unsafe bool) error { return nil } -func (m *Manager) SetUI(jobs *controller.Jobs, optimizations *controller.Optimizations) { +func (m *Manager) SetDefaultUI(jobs *controller.Jobs, optimizations *controller.Optimizations[golang.OptimizationItem]) { m.jobs = jobs m.optimizations = optimizations @@ -317,6 +327,22 @@ func (m *Manager) SetUI(jobs *controller.Jobs, optimizations *controller.Optimiz }) } +func (m *Manager) SetCustomUI(jobs *controller.Jobs, optimizations *controller.Optimizations[golang.ChartOptimizationItem]) { + m.jobs = jobs + m.pluginCustomOptimizations = optimizations + + optimizations.SetReEvaluateFunc(func(id string, items []*golang.PreferenceItem) { + m.stream.Send(&golang.ServerMessage{ + ServerMessage: &golang.ServerMessage_ReEvaluate{ + ReEvaluate: &golang.ReEvaluate{ + Id: id, + Preferences: items, + }, + }, + }) + }) +} + func (m *Manager) SetNonInteractiveView() { m.NonInteractiveView = view.NewNonInteractiveView() } diff --git a/pkg/plugin/proto/plugin.proto b/pkg/plugin/proto/plugin.proto index f98ab4b..03fddda 100644 --- a/pkg/plugin/proto/plugin.proto +++ b/pkg/plugin/proto/plugin.proto @@ -25,6 +25,28 @@ message RegisterConfig { string provider = 3; repeated Command commands = 4; string min_kaytu_version = 5; + + ChartDefinition overview_chart = 6; + ChartDefinition devices_chart = 7; +} + +message ChartRowItem { + string value = 1; +} + +message ChartRow { + string row_id = 1; + map values = 2; // Column Id -> Item +} + +message ChartColumnItem { + string id = 1; + string name = 2; + uint32 width = 3; +} + +message ChartDefinition { + repeated ChartColumnItem columns = 2; } message Error { @@ -47,6 +69,10 @@ message Property { bool hidden = 6; } +message Properties { + repeated Property properties = 1; +} + message Device { string device_id = 1; string resource_type = 2; @@ -83,6 +109,19 @@ message OptimizationItem { bool lazy_loading_enabled = 12; } +message ChartOptimizationItem { + ChartRow overview_chart_row = 1; + repeated PreferenceItem preferences = 2; + bool loading = 3; + bool skipped = 4; + google.protobuf.StringValue skip_reason = 5; + bool lazy_loading_enabled = 6; + string description = 7; + + repeated ChartRow devices_chart_rows = 8; + map devices_properties = 9; // Device Row id -> Row properties +} + message ResultsReady { bool ready = 1; } @@ -94,6 +133,7 @@ message PluginMessage { RegisterConfig conf = 3; Error err = 4; ResultsReady ready = 5; + ChartOptimizationItem coi = 6; } } diff --git a/pkg/plugin/proto/src/golang/plugin.pb.go b/pkg/plugin/proto/src/golang/plugin.pb.go index 99d71a8..c93a465 100644 --- a/pkg/plugin/proto/src/golang/plugin.pb.go +++ b/pkg/plugin/proto/src/golang/plugin.pb.go @@ -1,15 +1,15 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 -// protoc v3.12.4 +// protoc-gen-go v1.28.0 +// protoc v4.25.3 // source: pkg/plugin/proto/plugin.proto package golang import ( - wrappers "github.com/golang/protobuf/ptypes/wrappers" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" reflect "reflect" sync "sync" ) @@ -176,11 +176,13 @@ type RegisterConfig struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - Provider string `protobuf:"bytes,3,opt,name=provider,proto3" json:"provider,omitempty"` - Commands []*Command `protobuf:"bytes,4,rep,name=commands,proto3" json:"commands,omitempty"` - MinKaytuVersion string `protobuf:"bytes,5,opt,name=min_kaytu_version,json=minKaytuVersion,proto3" json:"min_kaytu_version,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` + Provider string `protobuf:"bytes,3,opt,name=provider,proto3" json:"provider,omitempty"` + Commands []*Command `protobuf:"bytes,4,rep,name=commands,proto3" json:"commands,omitempty"` + MinKaytuVersion string `protobuf:"bytes,5,opt,name=min_kaytu_version,json=minKaytuVersion,proto3" json:"min_kaytu_version,omitempty"` + OverviewChart *ChartDefinition `protobuf:"bytes,6,opt,name=overview_chart,json=overviewChart,proto3" json:"overview_chart,omitempty"` + DevicesChart *ChartDefinition `protobuf:"bytes,7,opt,name=devices_chart,json=devicesChart,proto3" json:"devices_chart,omitempty"` } func (x *RegisterConfig) Reset() { @@ -250,6 +252,232 @@ func (x *RegisterConfig) GetMinKaytuVersion() string { return "" } +func (x *RegisterConfig) GetOverviewChart() *ChartDefinition { + if x != nil { + return x.OverviewChart + } + return nil +} + +func (x *RegisterConfig) GetDevicesChart() *ChartDefinition { + if x != nil { + return x.DevicesChart + } + return nil +} + +type ChartRowItem struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *ChartRowItem) Reset() { + *x = ChartRowItem{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ChartRowItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChartRowItem) ProtoMessage() {} + +func (x *ChartRowItem) ProtoReflect() protoreflect.Message { + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChartRowItem.ProtoReflect.Descriptor instead. +func (*ChartRowItem) Descriptor() ([]byte, []int) { + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{3} +} + +func (x *ChartRowItem) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +type ChartRow struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RowId string `protobuf:"bytes,1,opt,name=row_id,json=rowId,proto3" json:"row_id,omitempty"` + Values map[string]*ChartRowItem `protobuf:"bytes,2,rep,name=values,proto3" json:"values,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // Column Id -> Item +} + +func (x *ChartRow) Reset() { + *x = ChartRow{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ChartRow) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChartRow) ProtoMessage() {} + +func (x *ChartRow) ProtoReflect() protoreflect.Message { + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChartRow.ProtoReflect.Descriptor instead. +func (*ChartRow) Descriptor() ([]byte, []int) { + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{4} +} + +func (x *ChartRow) GetRowId() string { + if x != nil { + return x.RowId + } + return "" +} + +func (x *ChartRow) GetValues() map[string]*ChartRowItem { + if x != nil { + return x.Values + } + return nil +} + +type ChartColumnItem struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Width uint32 `protobuf:"varint,3,opt,name=width,proto3" json:"width,omitempty"` +} + +func (x *ChartColumnItem) Reset() { + *x = ChartColumnItem{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ChartColumnItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChartColumnItem) ProtoMessage() {} + +func (x *ChartColumnItem) ProtoReflect() protoreflect.Message { + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChartColumnItem.ProtoReflect.Descriptor instead. +func (*ChartColumnItem) Descriptor() ([]byte, []int) { + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{5} +} + +func (x *ChartColumnItem) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *ChartColumnItem) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ChartColumnItem) GetWidth() uint32 { + if x != nil { + return x.Width + } + return 0 +} + +type ChartDefinition struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Columns []*ChartColumnItem `protobuf:"bytes,2,rep,name=columns,proto3" json:"columns,omitempty"` +} + +func (x *ChartDefinition) Reset() { + *x = ChartDefinition{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ChartDefinition) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChartDefinition) ProtoMessage() {} + +func (x *ChartDefinition) ProtoReflect() protoreflect.Message { + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChartDefinition.ProtoReflect.Descriptor instead. +func (*ChartDefinition) Descriptor() ([]byte, []int) { + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{6} +} + +func (x *ChartDefinition) GetColumns() []*ChartColumnItem { + if x != nil { + return x.Columns + } + return nil +} + type Error struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -261,7 +489,7 @@ type Error struct { func (x *Error) Reset() { *x = Error{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[3] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -274,7 +502,7 @@ func (x *Error) String() string { func (*Error) ProtoMessage() {} func (x *Error) ProtoReflect() protoreflect.Message { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[3] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -287,7 +515,7 @@ func (x *Error) ProtoReflect() protoreflect.Message { // Deprecated: Use Error.ProtoReflect.Descriptor instead. func (*Error) Descriptor() ([]byte, []int) { - return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{3} + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{7} } func (x *Error) GetError() string { @@ -311,7 +539,7 @@ type JobResult struct { func (x *JobResult) Reset() { *x = JobResult{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[4] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -324,7 +552,7 @@ func (x *JobResult) String() string { func (*JobResult) ProtoMessage() {} func (x *JobResult) ProtoReflect() protoreflect.Message { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[4] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -337,7 +565,7 @@ func (x *JobResult) ProtoReflect() protoreflect.Message { // Deprecated: Use JobResult.ProtoReflect.Descriptor instead. func (*JobResult) Descriptor() ([]byte, []int) { - return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{4} + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{8} } func (x *JobResult) GetId() string { @@ -384,7 +612,7 @@ type Property struct { func (x *Property) Reset() { *x = Property{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[5] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -397,7 +625,7 @@ func (x *Property) String() string { func (*Property) ProtoMessage() {} func (x *Property) ProtoReflect() protoreflect.Message { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[5] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -410,7 +638,7 @@ func (x *Property) ProtoReflect() protoreflect.Message { // Deprecated: Use Property.ProtoReflect.Descriptor instead. func (*Property) Descriptor() ([]byte, []int) { - return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{5} + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{9} } func (x *Property) GetKey() string { @@ -455,6 +683,53 @@ func (x *Property) GetHidden() bool { return false } +type Properties struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Properties []*Property `protobuf:"bytes,1,rep,name=properties,proto3" json:"properties,omitempty"` +} + +func (x *Properties) Reset() { + *x = Properties{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Properties) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Properties) ProtoMessage() {} + +func (x *Properties) ProtoReflect() protoreflect.Message { + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Properties.ProtoReflect.Descriptor instead. +func (*Properties) Descriptor() ([]byte, []int) { + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{10} +} + +func (x *Properties) GetProperties() []*Property { + if x != nil { + return x.Properties + } + return nil +} + type Device struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -471,7 +746,7 @@ type Device struct { func (x *Device) Reset() { *x = Device{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[6] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -484,7 +759,7 @@ func (x *Device) String() string { func (*Device) ProtoMessage() {} func (x *Device) ProtoReflect() protoreflect.Message { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[6] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -497,7 +772,7 @@ func (x *Device) ProtoReflect() protoreflect.Message { // Deprecated: Use Device.ProtoReflect.Descriptor instead. func (*Device) Descriptor() ([]byte, []int) { - return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{6} + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{11} } func (x *Device) GetDeviceId() string { @@ -547,21 +822,21 @@ type PreferenceItem struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Service string `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` - Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` - Alias string `protobuf:"bytes,3,opt,name=alias,proto3" json:"alias,omitempty"` - IsNumber bool `protobuf:"varint,4,opt,name=is_number,json=isNumber,proto3" json:"is_number,omitempty"` - Value *wrappers.StringValue `protobuf:"bytes,5,opt,name=value,proto3" json:"value,omitempty"` - PossibleValues []string `protobuf:"bytes,6,rep,name=possible_values,json=possibleValues,proto3" json:"possible_values,omitempty"` - Pinned bool `protobuf:"varint,7,opt,name=pinned,proto3" json:"pinned,omitempty"` - PreventPinning bool `protobuf:"varint,8,opt,name=prevent_pinning,json=preventPinning,proto3" json:"prevent_pinning,omitempty"` - Unit string `protobuf:"bytes,9,opt,name=unit,proto3" json:"unit,omitempty"` + Service string `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` + Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + Alias string `protobuf:"bytes,3,opt,name=alias,proto3" json:"alias,omitempty"` + IsNumber bool `protobuf:"varint,4,opt,name=is_number,json=isNumber,proto3" json:"is_number,omitempty"` + Value *wrapperspb.StringValue `protobuf:"bytes,5,opt,name=value,proto3" json:"value,omitempty"` + PossibleValues []string `protobuf:"bytes,6,rep,name=possible_values,json=possibleValues,proto3" json:"possible_values,omitempty"` + Pinned bool `protobuf:"varint,7,opt,name=pinned,proto3" json:"pinned,omitempty"` + PreventPinning bool `protobuf:"varint,8,opt,name=prevent_pinning,json=preventPinning,proto3" json:"prevent_pinning,omitempty"` + Unit string `protobuf:"bytes,9,opt,name=unit,proto3" json:"unit,omitempty"` } func (x *PreferenceItem) Reset() { *x = PreferenceItem{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[7] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -574,7 +849,7 @@ func (x *PreferenceItem) String() string { func (*PreferenceItem) ProtoMessage() {} func (x *PreferenceItem) ProtoReflect() protoreflect.Message { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[7] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -587,7 +862,7 @@ func (x *PreferenceItem) ProtoReflect() protoreflect.Message { // Deprecated: Use PreferenceItem.ProtoReflect.Descriptor instead. func (*PreferenceItem) Descriptor() ([]byte, []int) { - return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{7} + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{12} } func (x *PreferenceItem) GetService() string { @@ -618,7 +893,7 @@ func (x *PreferenceItem) GetIsNumber() bool { return false } -func (x *PreferenceItem) GetValue() *wrappers.StringValue { +func (x *PreferenceItem) GetValue() *wrapperspb.StringValue { if x != nil { return x.Value } @@ -675,7 +950,7 @@ type OptimizationItem struct { func (x *OptimizationItem) Reset() { *x = OptimizationItem{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[8] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -688,7 +963,7 @@ func (x *OptimizationItem) String() string { func (*OptimizationItem) ProtoMessage() {} func (x *OptimizationItem) ProtoReflect() protoreflect.Message { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[8] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -701,7 +976,7 @@ func (x *OptimizationItem) ProtoReflect() protoreflect.Message { // Deprecated: Use OptimizationItem.ProtoReflect.Descriptor instead. func (*OptimizationItem) Descriptor() ([]byte, []int) { - return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{8} + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{13} } func (x *OptimizationItem) GetId() string { @@ -788,6 +1063,117 @@ func (x *OptimizationItem) GetLazyLoadingEnabled() bool { return false } +type ChartOptimizationItem struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OverviewChartRow *ChartRow `protobuf:"bytes,1,opt,name=overview_chart_row,json=overviewChartRow,proto3" json:"overview_chart_row,omitempty"` + Preferences []*PreferenceItem `protobuf:"bytes,2,rep,name=preferences,proto3" json:"preferences,omitempty"` + Loading bool `protobuf:"varint,3,opt,name=loading,proto3" json:"loading,omitempty"` + Skipped bool `protobuf:"varint,4,opt,name=skipped,proto3" json:"skipped,omitempty"` + SkipReason *wrapperspb.StringValue `protobuf:"bytes,5,opt,name=skip_reason,json=skipReason,proto3" json:"skip_reason,omitempty"` + LazyLoadingEnabled bool `protobuf:"varint,6,opt,name=lazy_loading_enabled,json=lazyLoadingEnabled,proto3" json:"lazy_loading_enabled,omitempty"` + Description string `protobuf:"bytes,7,opt,name=description,proto3" json:"description,omitempty"` + DevicesChartRows []*ChartRow `protobuf:"bytes,8,rep,name=devices_chart_rows,json=devicesChartRows,proto3" json:"devices_chart_rows,omitempty"` + DevicesProperties map[string]*Properties `protobuf:"bytes,9,rep,name=devices_properties,json=devicesProperties,proto3" json:"devices_properties,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // Device Row id -> Row properties +} + +func (x *ChartOptimizationItem) Reset() { + *x = ChartOptimizationItem{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ChartOptimizationItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChartOptimizationItem) ProtoMessage() {} + +func (x *ChartOptimizationItem) ProtoReflect() protoreflect.Message { + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChartOptimizationItem.ProtoReflect.Descriptor instead. +func (*ChartOptimizationItem) Descriptor() ([]byte, []int) { + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{14} +} + +func (x *ChartOptimizationItem) GetOverviewChartRow() *ChartRow { + if x != nil { + return x.OverviewChartRow + } + return nil +} + +func (x *ChartOptimizationItem) GetPreferences() []*PreferenceItem { + if x != nil { + return x.Preferences + } + return nil +} + +func (x *ChartOptimizationItem) GetLoading() bool { + if x != nil { + return x.Loading + } + return false +} + +func (x *ChartOptimizationItem) GetSkipped() bool { + if x != nil { + return x.Skipped + } + return false +} + +func (x *ChartOptimizationItem) GetSkipReason() *wrapperspb.StringValue { + if x != nil { + return x.SkipReason + } + return nil +} + +func (x *ChartOptimizationItem) GetLazyLoadingEnabled() bool { + if x != nil { + return x.LazyLoadingEnabled + } + return false +} + +func (x *ChartOptimizationItem) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *ChartOptimizationItem) GetDevicesChartRows() []*ChartRow { + if x != nil { + return x.DevicesChartRows + } + return nil +} + +func (x *ChartOptimizationItem) GetDevicesProperties() map[string]*Properties { + if x != nil { + return x.DevicesProperties + } + return nil +} + type ResultsReady struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -799,7 +1185,7 @@ type ResultsReady struct { func (x *ResultsReady) Reset() { *x = ResultsReady{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[9] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -812,7 +1198,7 @@ func (x *ResultsReady) String() string { func (*ResultsReady) ProtoMessage() {} func (x *ResultsReady) ProtoReflect() protoreflect.Message { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[9] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -825,7 +1211,7 @@ func (x *ResultsReady) ProtoReflect() protoreflect.Message { // Deprecated: Use ResultsReady.ProtoReflect.Descriptor instead. func (*ResultsReady) Descriptor() ([]byte, []int) { - return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{9} + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{15} } func (x *ResultsReady) GetReady() bool { @@ -841,19 +1227,19 @@ type PluginMessage struct { unknownFields protoimpl.UnknownFields // Types that are assignable to PluginMessage: - // // *PluginMessage_Job // *PluginMessage_Oi // *PluginMessage_Conf // *PluginMessage_Err // *PluginMessage_Ready + // *PluginMessage_Coi PluginMessage isPluginMessage_PluginMessage `protobuf_oneof:"plugin_message"` } func (x *PluginMessage) Reset() { *x = PluginMessage{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[10] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -866,7 +1252,7 @@ func (x *PluginMessage) String() string { func (*PluginMessage) ProtoMessage() {} func (x *PluginMessage) ProtoReflect() protoreflect.Message { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[10] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -879,7 +1265,7 @@ func (x *PluginMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use PluginMessage.ProtoReflect.Descriptor instead. func (*PluginMessage) Descriptor() ([]byte, []int) { - return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{10} + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{16} } func (m *PluginMessage) GetPluginMessage() isPluginMessage_PluginMessage { @@ -924,6 +1310,13 @@ func (x *PluginMessage) GetReady() *ResultsReady { return nil } +func (x *PluginMessage) GetCoi() *ChartOptimizationItem { + if x, ok := x.GetPluginMessage().(*PluginMessage_Coi); ok { + return x.Coi + } + return nil +} + type isPluginMessage_PluginMessage interface { isPluginMessage_PluginMessage() } @@ -948,6 +1341,10 @@ type PluginMessage_Ready struct { Ready *ResultsReady `protobuf:"bytes,5,opt,name=ready,proto3,oneof"` } +type PluginMessage_Coi struct { + Coi *ChartOptimizationItem `protobuf:"bytes,6,opt,name=coi,proto3,oneof"` +} + func (*PluginMessage_Job) isPluginMessage_PluginMessage() {} func (*PluginMessage_Oi) isPluginMessage_PluginMessage() {} @@ -958,6 +1355,8 @@ func (*PluginMessage_Err) isPluginMessage_PluginMessage() {} func (*PluginMessage_Ready) isPluginMessage_PluginMessage() {} +func (*PluginMessage_Coi) isPluginMessage_PluginMessage() {} + type ReEvaluate struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -970,7 +1369,7 @@ type ReEvaluate struct { func (x *ReEvaluate) Reset() { *x = ReEvaluate{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[11] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -983,7 +1382,7 @@ func (x *ReEvaluate) String() string { func (*ReEvaluate) ProtoMessage() {} func (x *ReEvaluate) ProtoReflect() protoreflect.Message { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[11] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -996,7 +1395,7 @@ func (x *ReEvaluate) ProtoReflect() protoreflect.Message { // Deprecated: Use ReEvaluate.ProtoReflect.Descriptor instead. func (*ReEvaluate) Descriptor() ([]byte, []int) { - return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{11} + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{17} } func (x *ReEvaluate) GetId() string { @@ -1026,7 +1425,7 @@ type StartProcess struct { func (x *StartProcess) Reset() { *x = StartProcess{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[12] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1039,7 +1438,7 @@ func (x *StartProcess) String() string { func (*StartProcess) ProtoMessage() {} func (x *StartProcess) ProtoReflect() protoreflect.Message { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[12] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1052,7 +1451,7 @@ func (x *StartProcess) ProtoReflect() protoreflect.Message { // Deprecated: Use StartProcess.ProtoReflect.Descriptor instead. func (*StartProcess) Descriptor() ([]byte, []int) { - return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{12} + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{18} } func (x *StartProcess) GetCommand() string { @@ -1082,7 +1481,6 @@ type ServerMessage struct { unknownFields protoimpl.UnknownFields // Types that are assignable to ServerMessage: - // // *ServerMessage_ReEvaluate // *ServerMessage_Start ServerMessage isServerMessage_ServerMessage `protobuf_oneof:"server_message"` @@ -1091,7 +1489,7 @@ type ServerMessage struct { func (x *ServerMessage) Reset() { *x = ServerMessage{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[13] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1104,7 +1502,7 @@ func (x *ServerMessage) String() string { func (*ServerMessage) ProtoMessage() {} func (x *ServerMessage) ProtoReflect() protoreflect.Message { - mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[13] + mi := &file_pkg_plugin_proto_plugin_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1117,7 +1515,7 @@ func (x *ServerMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use ServerMessage.ProtoReflect.Descriptor instead. func (*ServerMessage) Descriptor() ([]byte, []int) { - return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{13} + return file_pkg_plugin_proto_plugin_proto_rawDescGZIP(), []int{19} } func (m *ServerMessage) GetServerMessage() isServerMessage_ServerMessage { @@ -1186,7 +1584,7 @@ var file_pkg_plugin_proto_plugin_proto_rawDesc = []byte{ 0x6d, 0x52, 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6c, - 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x22, 0xbc, 0x01, 0x0a, + 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x22, 0xcc, 0x02, 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, @@ -1198,146 +1596,227 @@ var file_pkg_plugin_proto_plugin_proto_rawDesc = []byte{ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x5f, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x4b, - 0x61, 0x79, 0x74, 0x75, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x1d, 0x0a, 0x05, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x7a, 0x0a, 0x09, 0x4a, 0x6f, - 0x62, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x66, 0x61, 0x69, - 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x6f, 0x6e, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x04, 0x64, 0x6f, 0x6e, 0x65, 0x22, 0x9c, 0x01, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x70, 0x65, - 0x72, 0x74, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, - 0x18, 0x0a, 0x07, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x61, 0x78, 0x12, 0x20, 0x0a, 0x0b, 0x72, - 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x16, 0x0a, - 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, - 0x69, 0x64, 0x64, 0x65, 0x6e, 0x22, 0xec, 0x01, 0x0a, 0x06, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, - 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x01, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x73, 0x74, 0x12, - 0x28, 0x0a, 0x10, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, - 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0e, 0x72, 0x69, 0x67, 0x68, 0x74, - 0x53, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, - 0x74, 0x69, 0x65, 0x73, 0x22, 0xa1, 0x02, 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, - 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x6f, - 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x70, - 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x69, 0x6e, - 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x22, 0xae, 0x03, 0x0a, 0x10, 0x4f, 0x70, 0x74, - 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x1a, - 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x31, 0x0a, 0x07, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6b, 0x61, - 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x41, 0x0a, - 0x0b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x49, - 0x74, 0x65, 0x6d, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, - 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x07, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, - 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, - 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x72, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6b, 0x69, - 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x14, 0x6c, 0x61, 0x7a, 0x79, 0x5f, - 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, - 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x6c, 0x61, 0x7a, 0x79, 0x4c, 0x6f, 0x61, 0x64, 0x69, - 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x24, 0x0a, 0x0c, 0x52, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x73, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x61, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x22, - 0xa0, 0x02, 0x0a, 0x0d, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x2e, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x03, 0x6a, 0x6f, - 0x62, 0x12, 0x33, 0x0a, 0x02, 0x6f, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, - 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, - 0x48, 0x00, 0x52, 0x02, 0x6f, 0x69, 0x12, 0x35, 0x0a, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, - 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x12, 0x2a, 0x0a, - 0x03, 0x65, 0x72, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6b, 0x61, 0x79, - 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x48, 0x00, 0x52, 0x03, 0x65, 0x72, 0x72, 0x12, 0x35, 0x0a, 0x05, 0x72, 0x65, 0x61, - 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, - 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x73, 0x52, 0x65, 0x61, 0x64, 0x79, 0x48, 0x00, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, - 0x42, 0x10, 0x0a, 0x0e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x22, 0x5f, 0x0a, 0x0a, 0x52, 0x65, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x41, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, - 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x73, 0x22, 0xd0, 0x01, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x3e, - 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, + 0x61, 0x79, 0x74, 0x75, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x0e, 0x6f, + 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x6f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x43, + 0x68, 0x61, 0x72, 0x74, 0x12, 0x45, 0x0a, 0x0d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, + 0x63, 0x68, 0x61, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6b, 0x61, + 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, + 0x61, 0x72, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x68, 0x61, 0x72, 0x74, 0x22, 0x24, 0x0a, 0x0c, 0x43, + 0x68, 0x61, 0x72, 0x74, 0x52, 0x6f, 0x77, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0xba, 0x01, 0x0a, 0x08, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x6f, 0x77, 0x12, 0x15, + 0x0a, 0x06, 0x72, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x72, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x3d, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x6f, 0x77, + 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x1a, 0x58, 0x0a, 0x0b, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x33, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x6f, 0x77, 0x49, + 0x74, 0x65, 0x6d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4b, + 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x49, 0x74, 0x65, + 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x4d, 0x0a, 0x0f, 0x43, + 0x68, 0x61, 0x72, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, + 0x0a, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x20, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x49, 0x74, 0x65, + 0x6d, 0x52, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x22, 0x1d, 0x0a, 0x05, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x7a, 0x0a, 0x09, 0x4a, 0x6f, 0x62, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x66, 0x61, 0x69, 0x6c, + 0x75, 0x72, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x6f, 0x6e, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x04, 0x64, 0x6f, 0x6e, 0x65, 0x22, 0x9c, 0x01, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, + 0x74, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x18, + 0x0a, 0x07, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x61, 0x78, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, + 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, + 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, 0x69, + 0x64, 0x64, 0x65, 0x6e, 0x22, 0x47, 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, + 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, + 0x79, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0xec, 0x01, + 0x0a, 0x06, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x75, + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, + 0x63, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x69, 0x67, 0x68, 0x74, + 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x01, 0x52, 0x0e, 0x72, 0x69, 0x67, 0x68, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x73, + 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, + 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, + 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0xa1, 0x02, 0x0a, + 0x0e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x12, + 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x61, + 0x6c, 0x69, 0x61, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x61, + 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x32, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x6f, 0x73, + 0x73, 0x69, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x70, + 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x69, 0x6e, + 0x6e, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x70, + 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, 0x72, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, + 0x75, 0x6e, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x6e, 0x69, 0x74, + 0x22, 0xae, 0x03, 0x0a, 0x10, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, + 0x72, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, + 0x72, 0x6d, 0x12, 0x31, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x06, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6b, 0x61, 0x79, + 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, + 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0b, 0x70, 0x72, 0x65, + 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x6f, + 0x61, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6c, 0x6f, 0x61, + 0x64, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x12, 0x1f, + 0x0a, 0x0b, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6b, 0x69, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, + 0x30, 0x0a, 0x14, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x6c, + 0x61, 0x7a, 0x79, 0x4c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x22, 0x84, 0x05, 0x0a, 0x15, 0x43, 0x68, 0x61, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x47, 0x0a, 0x12, 0x6f, + 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x5f, 0x72, 0x6f, + 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, + 0x6f, 0x77, 0x52, 0x10, 0x6f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x43, 0x68, 0x61, 0x72, + 0x74, 0x52, 0x6f, 0x77, 0x12, 0x41, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6b, 0x61, 0x79, 0x74, + 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x6f, 0x61, 0x64, 0x69, + 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, + 0x67, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x0b, 0x73, + 0x6b, 0x69, 0x70, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, + 0x73, 0x6b, 0x69, 0x70, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x14, 0x6c, 0x61, + 0x7a, 0x79, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x6c, 0x61, 0x7a, 0x79, 0x4c, 0x6f, + 0x61, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, + 0x0a, 0x12, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x5f, + 0x72, 0x6f, 0x77, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6b, 0x61, 0x79, + 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, + 0x72, 0x74, 0x52, 0x6f, 0x77, 0x52, 0x10, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x43, 0x68, + 0x61, 0x72, 0x74, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x6c, 0x0a, 0x12, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x09, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x11, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x70, 0x65, + 0x72, 0x74, 0x69, 0x65, 0x73, 0x1a, 0x61, 0x0a, 0x16, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x24, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x73, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x61, 0x64, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x22, 0xdc, + 0x02, 0x0a, 0x0d, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x2e, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x2e, 0x46, 0x6c, 0x61, - 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x2c, - 0x0a, 0x12, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6b, 0x61, 0x79, 0x74, - 0x75, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0x38, 0x0a, 0x0a, - 0x46, 0x6c, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x98, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x72, 0x65, 0x5f, 0x65, - 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, - 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x65, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x0a, 0x72, 0x65, - 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x12, 0x35, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, - 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, - 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x42, - 0x10, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x32, 0x5a, 0x0a, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x50, 0x0a, 0x08, 0x52, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, - 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1e, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, - 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x2c, 0x5a, - 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x79, 0x74, - 0x75, 0x2d, 0x69, 0x6f, 0x2f, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x73, 0x72, 0x63, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x03, 0x6a, 0x6f, 0x62, + 0x12, 0x33, 0x0a, 0x02, 0x6f, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6b, + 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4f, + 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x48, + 0x00, 0x52, 0x02, 0x6f, 0x69, 0x12, 0x35, 0x0a, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x12, 0x2a, 0x0a, 0x03, + 0x65, 0x72, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6b, 0x61, 0x79, 0x74, + 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x48, 0x00, 0x52, 0x03, 0x65, 0x72, 0x72, 0x12, 0x35, 0x0a, 0x05, 0x72, 0x65, 0x61, 0x64, + 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x73, 0x52, 0x65, 0x61, 0x64, 0x79, 0x48, 0x00, 0x52, 0x05, 0x72, 0x65, 0x61, 0x64, 0x79, 0x12, + 0x3a, 0x0a, 0x03, 0x63, 0x6f, 0x69, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x6b, + 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x68, 0x61, 0x72, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x74, 0x65, 0x6d, 0x48, 0x00, 0x52, 0x03, 0x63, 0x6f, 0x69, 0x42, 0x10, 0x0a, 0x0e, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x5f, 0x0a, + 0x0a, 0x52, 0x65, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x41, 0x0a, 0x0b, 0x70, + 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1f, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x74, 0x65, + 0x6d, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x22, 0xd0, + 0x01, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, + 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x3e, 0x0a, 0x05, 0x66, 0x6c, 0x61, + 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, + 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x2e, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x6b, 0x61, 0x79, + 0x74, 0x75, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0x38, 0x0a, 0x0a, 0x46, 0x6c, 0x61, 0x67, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0x98, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x72, 0x65, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, + 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, + 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x45, 0x76, 0x61, + 0x6c, 0x75, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x0a, 0x72, 0x65, 0x45, 0x76, 0x61, 0x6c, 0x75, + 0x61, 0x74, 0x65, 0x12, 0x35, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, + 0x73, 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x42, 0x10, 0x0a, 0x0e, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x5a, 0x0a, 0x06, + 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x50, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x1a, 0x1e, 0x2e, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2d, 0x69, 0x6f, 0x2f, + 0x6b, 0x61, 0x79, 0x74, 0x75, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x72, 0x63, 0x2f, + 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1352,49 +1831,70 @@ func file_pkg_plugin_proto_plugin_proto_rawDescGZIP() []byte { return file_pkg_plugin_proto_plugin_proto_rawDescData } -var file_pkg_plugin_proto_plugin_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_pkg_plugin_proto_plugin_proto_msgTypes = make([]protoimpl.MessageInfo, 23) var file_pkg_plugin_proto_plugin_proto_goTypes = []interface{}{ - (*Flag)(nil), // 0: kaytu.plugin.v1.Flag - (*Command)(nil), // 1: kaytu.plugin.v1.Command - (*RegisterConfig)(nil), // 2: kaytu.plugin.v1.RegisterConfig - (*Error)(nil), // 3: kaytu.plugin.v1.Error - (*JobResult)(nil), // 4: kaytu.plugin.v1.JobResult - (*Property)(nil), // 5: kaytu.plugin.v1.Property - (*Device)(nil), // 6: kaytu.plugin.v1.Device - (*PreferenceItem)(nil), // 7: kaytu.plugin.v1.PreferenceItem - (*OptimizationItem)(nil), // 8: kaytu.plugin.v1.OptimizationItem - (*ResultsReady)(nil), // 9: kaytu.plugin.v1.ResultsReady - (*PluginMessage)(nil), // 10: kaytu.plugin.v1.PluginMessage - (*ReEvaluate)(nil), // 11: kaytu.plugin.v1.ReEvaluate - (*StartProcess)(nil), // 12: kaytu.plugin.v1.StartProcess - (*ServerMessage)(nil), // 13: kaytu.plugin.v1.ServerMessage - nil, // 14: kaytu.plugin.v1.StartProcess.FlagsEntry - (*wrappers.StringValue)(nil), // 15: google.protobuf.StringValue + (*Flag)(nil), // 0: kaytu.plugin.v1.Flag + (*Command)(nil), // 1: kaytu.plugin.v1.Command + (*RegisterConfig)(nil), // 2: kaytu.plugin.v1.RegisterConfig + (*ChartRowItem)(nil), // 3: kaytu.plugin.v1.ChartRowItem + (*ChartRow)(nil), // 4: kaytu.plugin.v1.ChartRow + (*ChartColumnItem)(nil), // 5: kaytu.plugin.v1.ChartColumnItem + (*ChartDefinition)(nil), // 6: kaytu.plugin.v1.ChartDefinition + (*Error)(nil), // 7: kaytu.plugin.v1.Error + (*JobResult)(nil), // 8: kaytu.plugin.v1.JobResult + (*Property)(nil), // 9: kaytu.plugin.v1.Property + (*Properties)(nil), // 10: kaytu.plugin.v1.Properties + (*Device)(nil), // 11: kaytu.plugin.v1.Device + (*PreferenceItem)(nil), // 12: kaytu.plugin.v1.PreferenceItem + (*OptimizationItem)(nil), // 13: kaytu.plugin.v1.OptimizationItem + (*ChartOptimizationItem)(nil), // 14: kaytu.plugin.v1.ChartOptimizationItem + (*ResultsReady)(nil), // 15: kaytu.plugin.v1.ResultsReady + (*PluginMessage)(nil), // 16: kaytu.plugin.v1.PluginMessage + (*ReEvaluate)(nil), // 17: kaytu.plugin.v1.ReEvaluate + (*StartProcess)(nil), // 18: kaytu.plugin.v1.StartProcess + (*ServerMessage)(nil), // 19: kaytu.plugin.v1.ServerMessage + nil, // 20: kaytu.plugin.v1.ChartRow.ValuesEntry + nil, // 21: kaytu.plugin.v1.ChartOptimizationItem.DevicesPropertiesEntry + nil, // 22: kaytu.plugin.v1.StartProcess.FlagsEntry + (*wrapperspb.StringValue)(nil), // 23: google.protobuf.StringValue } var file_pkg_plugin_proto_plugin_proto_depIdxs = []int32{ 0, // 0: kaytu.plugin.v1.Command.flags:type_name -> kaytu.plugin.v1.Flag - 7, // 1: kaytu.plugin.v1.Command.default_preferences:type_name -> kaytu.plugin.v1.PreferenceItem + 12, // 1: kaytu.plugin.v1.Command.default_preferences:type_name -> kaytu.plugin.v1.PreferenceItem 1, // 2: kaytu.plugin.v1.RegisterConfig.commands:type_name -> kaytu.plugin.v1.Command - 5, // 3: kaytu.plugin.v1.Device.properties:type_name -> kaytu.plugin.v1.Property - 15, // 4: kaytu.plugin.v1.PreferenceItem.value:type_name -> google.protobuf.StringValue - 6, // 5: kaytu.plugin.v1.OptimizationItem.devices:type_name -> kaytu.plugin.v1.Device - 7, // 6: kaytu.plugin.v1.OptimizationItem.preferences:type_name -> kaytu.plugin.v1.PreferenceItem - 4, // 7: kaytu.plugin.v1.PluginMessage.job:type_name -> kaytu.plugin.v1.JobResult - 8, // 8: kaytu.plugin.v1.PluginMessage.oi:type_name -> kaytu.plugin.v1.OptimizationItem - 2, // 9: kaytu.plugin.v1.PluginMessage.conf:type_name -> kaytu.plugin.v1.RegisterConfig - 3, // 10: kaytu.plugin.v1.PluginMessage.err:type_name -> kaytu.plugin.v1.Error - 9, // 11: kaytu.plugin.v1.PluginMessage.ready:type_name -> kaytu.plugin.v1.ResultsReady - 7, // 12: kaytu.plugin.v1.ReEvaluate.preferences:type_name -> kaytu.plugin.v1.PreferenceItem - 14, // 13: kaytu.plugin.v1.StartProcess.flags:type_name -> kaytu.plugin.v1.StartProcess.FlagsEntry - 11, // 14: kaytu.plugin.v1.ServerMessage.re_evaluate:type_name -> kaytu.plugin.v1.ReEvaluate - 12, // 15: kaytu.plugin.v1.ServerMessage.start:type_name -> kaytu.plugin.v1.StartProcess - 10, // 16: kaytu.plugin.v1.Plugin.Register:input_type -> kaytu.plugin.v1.PluginMessage - 13, // 17: kaytu.plugin.v1.Plugin.Register:output_type -> kaytu.plugin.v1.ServerMessage - 17, // [17:18] is the sub-list for method output_type - 16, // [16:17] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name + 6, // 3: kaytu.plugin.v1.RegisterConfig.overview_chart:type_name -> kaytu.plugin.v1.ChartDefinition + 6, // 4: kaytu.plugin.v1.RegisterConfig.devices_chart:type_name -> kaytu.plugin.v1.ChartDefinition + 20, // 5: kaytu.plugin.v1.ChartRow.values:type_name -> kaytu.plugin.v1.ChartRow.ValuesEntry + 5, // 6: kaytu.plugin.v1.ChartDefinition.columns:type_name -> kaytu.plugin.v1.ChartColumnItem + 9, // 7: kaytu.plugin.v1.Properties.properties:type_name -> kaytu.plugin.v1.Property + 9, // 8: kaytu.plugin.v1.Device.properties:type_name -> kaytu.plugin.v1.Property + 23, // 9: kaytu.plugin.v1.PreferenceItem.value:type_name -> google.protobuf.StringValue + 11, // 10: kaytu.plugin.v1.OptimizationItem.devices:type_name -> kaytu.plugin.v1.Device + 12, // 11: kaytu.plugin.v1.OptimizationItem.preferences:type_name -> kaytu.plugin.v1.PreferenceItem + 4, // 12: kaytu.plugin.v1.ChartOptimizationItem.overview_chart_row:type_name -> kaytu.plugin.v1.ChartRow + 12, // 13: kaytu.plugin.v1.ChartOptimizationItem.preferences:type_name -> kaytu.plugin.v1.PreferenceItem + 23, // 14: kaytu.plugin.v1.ChartOptimizationItem.skip_reason:type_name -> google.protobuf.StringValue + 4, // 15: kaytu.plugin.v1.ChartOptimizationItem.devices_chart_rows:type_name -> kaytu.plugin.v1.ChartRow + 21, // 16: kaytu.plugin.v1.ChartOptimizationItem.devices_properties:type_name -> kaytu.plugin.v1.ChartOptimizationItem.DevicesPropertiesEntry + 8, // 17: kaytu.plugin.v1.PluginMessage.job:type_name -> kaytu.plugin.v1.JobResult + 13, // 18: kaytu.plugin.v1.PluginMessage.oi:type_name -> kaytu.plugin.v1.OptimizationItem + 2, // 19: kaytu.plugin.v1.PluginMessage.conf:type_name -> kaytu.plugin.v1.RegisterConfig + 7, // 20: kaytu.plugin.v1.PluginMessage.err:type_name -> kaytu.plugin.v1.Error + 15, // 21: kaytu.plugin.v1.PluginMessage.ready:type_name -> kaytu.plugin.v1.ResultsReady + 14, // 22: kaytu.plugin.v1.PluginMessage.coi:type_name -> kaytu.plugin.v1.ChartOptimizationItem + 12, // 23: kaytu.plugin.v1.ReEvaluate.preferences:type_name -> kaytu.plugin.v1.PreferenceItem + 22, // 24: kaytu.plugin.v1.StartProcess.flags:type_name -> kaytu.plugin.v1.StartProcess.FlagsEntry + 17, // 25: kaytu.plugin.v1.ServerMessage.re_evaluate:type_name -> kaytu.plugin.v1.ReEvaluate + 18, // 26: kaytu.plugin.v1.ServerMessage.start:type_name -> kaytu.plugin.v1.StartProcess + 3, // 27: kaytu.plugin.v1.ChartRow.ValuesEntry.value:type_name -> kaytu.plugin.v1.ChartRowItem + 10, // 28: kaytu.plugin.v1.ChartOptimizationItem.DevicesPropertiesEntry.value:type_name -> kaytu.plugin.v1.Properties + 16, // 29: kaytu.plugin.v1.Plugin.Register:input_type -> kaytu.plugin.v1.PluginMessage + 19, // 30: kaytu.plugin.v1.Plugin.Register:output_type -> kaytu.plugin.v1.ServerMessage + 30, // [30:31] is the sub-list for method output_type + 29, // [29:30] is the sub-list for method input_type + 29, // [29:29] is the sub-list for extension type_name + 29, // [29:29] is the sub-list for extension extendee + 0, // [0:29] is the sub-list for field type_name } func init() { file_pkg_plugin_proto_plugin_proto_init() } @@ -1440,7 +1940,7 @@ func file_pkg_plugin_proto_plugin_proto_init() { } } file_pkg_plugin_proto_plugin_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Error); i { + switch v := v.(*ChartRowItem); i { case 0: return &v.state case 1: @@ -1452,7 +1952,7 @@ func file_pkg_plugin_proto_plugin_proto_init() { } } file_pkg_plugin_proto_plugin_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*JobResult); i { + switch v := v.(*ChartRow); i { case 0: return &v.state case 1: @@ -1464,7 +1964,7 @@ func file_pkg_plugin_proto_plugin_proto_init() { } } file_pkg_plugin_proto_plugin_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Property); i { + switch v := v.(*ChartColumnItem); i { case 0: return &v.state case 1: @@ -1476,7 +1976,7 @@ func file_pkg_plugin_proto_plugin_proto_init() { } } file_pkg_plugin_proto_plugin_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Device); i { + switch v := v.(*ChartDefinition); i { case 0: return &v.state case 1: @@ -1488,7 +1988,7 @@ func file_pkg_plugin_proto_plugin_proto_init() { } } file_pkg_plugin_proto_plugin_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PreferenceItem); i { + switch v := v.(*Error); i { case 0: return &v.state case 1: @@ -1500,7 +2000,7 @@ func file_pkg_plugin_proto_plugin_proto_init() { } } file_pkg_plugin_proto_plugin_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OptimizationItem); i { + switch v := v.(*JobResult); i { case 0: return &v.state case 1: @@ -1512,7 +2012,7 @@ func file_pkg_plugin_proto_plugin_proto_init() { } } file_pkg_plugin_proto_plugin_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResultsReady); i { + switch v := v.(*Property); i { case 0: return &v.state case 1: @@ -1524,7 +2024,7 @@ func file_pkg_plugin_proto_plugin_proto_init() { } } file_pkg_plugin_proto_plugin_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PluginMessage); i { + switch v := v.(*Properties); i { case 0: return &v.state case 1: @@ -1536,7 +2036,7 @@ func file_pkg_plugin_proto_plugin_proto_init() { } } file_pkg_plugin_proto_plugin_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReEvaluate); i { + switch v := v.(*Device); i { case 0: return &v.state case 1: @@ -1548,7 +2048,7 @@ func file_pkg_plugin_proto_plugin_proto_init() { } } file_pkg_plugin_proto_plugin_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartProcess); i { + switch v := v.(*PreferenceItem); i { case 0: return &v.state case 1: @@ -1560,6 +2060,78 @@ func file_pkg_plugin_proto_plugin_proto_init() { } } file_pkg_plugin_proto_plugin_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OptimizationItem); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_plugin_proto_plugin_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ChartOptimizationItem); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_plugin_proto_plugin_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResultsReady); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_plugin_proto_plugin_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PluginMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_plugin_proto_plugin_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReEvaluate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_plugin_proto_plugin_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StartProcess); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_plugin_proto_plugin_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServerMessage); i { case 0: return &v.state @@ -1572,14 +2144,15 @@ func file_pkg_plugin_proto_plugin_proto_init() { } } } - file_pkg_plugin_proto_plugin_proto_msgTypes[10].OneofWrappers = []interface{}{ + file_pkg_plugin_proto_plugin_proto_msgTypes[16].OneofWrappers = []interface{}{ (*PluginMessage_Job)(nil), (*PluginMessage_Oi)(nil), (*PluginMessage_Conf)(nil), (*PluginMessage_Err)(nil), (*PluginMessage_Ready)(nil), + (*PluginMessage_Coi)(nil), } - file_pkg_plugin_proto_plugin_proto_msgTypes[13].OneofWrappers = []interface{}{ + file_pkg_plugin_proto_plugin_proto_msgTypes[19].OneofWrappers = []interface{}{ (*ServerMessage_ReEvaluate)(nil), (*ServerMessage_Start)(nil), } @@ -1589,7 +2162,7 @@ func file_pkg_plugin_proto_plugin_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_plugin_proto_plugin_proto_rawDesc, NumEnums: 0, - NumMessages: 15, + NumMessages: 23, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/plugin/proto/src/golang/plugin_grpc.pb.go b/pkg/plugin/proto/src/golang/plugin_grpc.pb.go index 93e5e8e..582cdd1 100644 --- a/pkg/plugin/proto/src/golang/plugin_grpc.pb.go +++ b/pkg/plugin/proto/src/golang/plugin_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc v3.12.4 +// - protoc-gen-go-grpc v1.2.0 +// - protoc v4.25.3 // source: pkg/plugin/proto/plugin.proto package golang @@ -18,10 +18,6 @@ import ( // Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 -const ( - Plugin_Register_FullMethodName = "/kaytu.plugin.v1.Plugin/Register" -) - // PluginClient is the client API for Plugin service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. @@ -38,7 +34,7 @@ func NewPluginClient(cc grpc.ClientConnInterface) PluginClient { } func (c *pluginClient) Register(ctx context.Context, opts ...grpc.CallOption) (Plugin_RegisterClient, error) { - stream, err := c.cc.NewStream(ctx, &Plugin_ServiceDesc.Streams[0], Plugin_Register_FullMethodName, opts...) + stream, err := c.cc.NewStream(ctx, &Plugin_ServiceDesc.Streams[0], "/kaytu.plugin.v1.Plugin/Register", opts...) if err != nil { return nil, err } diff --git a/view/app.go b/view/app.go index 647c29f..6ec835d 100644 --- a/view/app.go +++ b/view/app.go @@ -2,6 +2,7 @@ package view import ( tea "github.com/charmbracelet/bubbletea" + "github.com/kaytu-io/kaytu/pkg/plugin/proto/src/golang" "github.com/kaytu-io/kaytu/view/responsive" "time" ) @@ -37,7 +38,25 @@ type App struct { func NewApp( optimizationsPage OverviewPage, optimizationDetailsPage ResourceDetailsPage, - preferencesPage PreferencesPage, + preferencesPage PreferencesPage[golang.OptimizationItem], + jobsPage JobsPage, +) *App { + app := &App{} + optimizationsPage = optimizationsPage.SetApp(app) + optimizationDetailsPage = optimizationDetailsPage.SetApp(app) + app.pages = []Page{ + optimizationsPage, + optimizationDetailsPage, + preferencesPage, + jobsPage, + } + return app +} + +func NewCustomPluginApp( + optimizationsPage PluginCustomOverviewPage, + optimizationDetailsPage PluginCustomResourceDetailsPage, + preferencesPage PreferencesPage[golang.ChartOptimizationItem], jobsPage JobsPage, ) *App { app := &App{} diff --git a/view/page_overview.go b/view/page_overview.go index 523cb37..b9ec680 100644 --- a/view/page_overview.go +++ b/view/page_overview.go @@ -5,6 +5,7 @@ import ( tea "github.com/charmbracelet/bubbletea" "github.com/evertras/bubble-table/table" "github.com/kaytu-io/kaytu/controller" + "github.com/kaytu-io/kaytu/pkg/plugin/proto/src/golang" "github.com/kaytu-io/kaytu/pkg/style" "github.com/kaytu-io/kaytu/pkg/utils" "github.com/kaytu-io/kaytu/view/responsive" @@ -15,7 +16,7 @@ type OverviewPage struct { clearScreen bool helpController *controller.Help - optimizations *controller.Optimizations + optimizations *controller.Optimizations[golang.OptimizationItem] statusBar StatusBarView app *App @@ -23,7 +24,7 @@ type OverviewPage struct { } func NewOptimizationsView( - optimizations *controller.Optimizations, + optimizations *controller.Optimizations[golang.OptimizationItem], helpController *controller.Help, statusBar StatusBarView, ) OverviewPage { @@ -36,6 +37,7 @@ func NewOptimizationsView( table.NewColumn("5", "Total Saving (Monthly)", 40), table.NewColumn("6", "", 1), } + t := table.New(columns). Focused(true). WithPageSize(10). @@ -51,9 +53,11 @@ func NewOptimizationsView( statusBar: statusBar, } } + func (m OverviewPage) OnClose() Page { return m } + func (m OverviewPage) OnOpen() Page { m.helpController.SetKeyMap([]string{ "↑/↓: move", diff --git a/view/page_overview_plugin_custom.go b/view/page_overview_plugin_custom.go new file mode 100644 index 0000000..74cb0ce --- /dev/null +++ b/view/page_overview_plugin_custom.go @@ -0,0 +1,188 @@ +package view + +import ( + tea "github.com/charmbracelet/bubbletea" + "github.com/evertras/bubble-table/table" + "github.com/kaytu-io/kaytu/controller" + "github.com/kaytu-io/kaytu/pkg/plugin/proto/src/golang" + "github.com/kaytu-io/kaytu/pkg/style" + "github.com/kaytu-io/kaytu/view/responsive" +) + +type PluginCustomOverviewPage struct { + table table.Model + clearScreen bool + + helpController *controller.Help + optimizations *controller.Optimizations[golang.ChartOptimizationItem] + statusBar StatusBarView + app *App + + responsive.ResponsiveView +} + +func NewPluginCustomOverviewPageView( + chartDefinition *golang.ChartDefinition, + optimizations *controller.Optimizations[golang.ChartOptimizationItem], + helpController *controller.Help, + statusBar StatusBarView, +) PluginCustomOverviewPage { + var columns []table.Column + tableColumnIdToIndex := make(map[string]int) + for i, column := range chartDefinition.GetColumns() { + columns = append(columns, table.NewColumn(column.GetId(), column.GetName(), int(column.GetWidth()))) + tableColumnIdToIndex[column.GetId()] = i + } + t := table.New(columns). + Focused(true). + WithPageSize(10). + WithHorizontalFreezeColumnCount(1). + WithBaseStyle(style.ActiveStyleBase). + BorderRounded(). + HighlightStyle(style.HighlightStyle) + + return PluginCustomOverviewPage{ + optimizations: optimizations, + helpController: helpController, + table: t, + statusBar: statusBar, + } +} + +func (m PluginCustomOverviewPage) OnClose() Page { + return m +} + +func (m PluginCustomOverviewPage) OnOpen() Page { + m.helpController.SetKeyMap([]string{ + "↑/↓: move", + "pgdown/pgup: next/prev page", + "←/→: scroll in the table", + "enter: see resource details", + "p: change preferences", + "P: change preferences for all resources", + "r: load all items in current page", + "ctrl+j: list of jobs", + "q/ctrl+c: exit", + }) + return m +} + +func (m PluginCustomOverviewPage) Init() tea.Cmd { + return nil +} + +func (m PluginCustomOverviewPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + var rows RowsWithId + + for _, i := range m.optimizations.Items() { + rowValues := make(map[string]string) + for k, value := range i.GetOverviewChartRow().GetValues() { + rowValues[k] = value.GetValue() + } + row := RowWithId{ + ID: i.GetOverviewChartRow().GetRowId(), + Row: rowValues, + } + rows = append(rows, row) + } + m.table = m.table.WithRows(rows.ToTableRows()) + + var changePageCmd tea.Cmd + switch msg := msg.(type) { + case tea.KeyMsg: + key := msg.String() + switch key { + case "pgdown": + m.table.PageDown() + case "pgup": + m.table.PageUp() + case "home": + m.table.PageFirst() + case "end": + m.table.PageLast() + case "q": + return m, tea.Quit + case "p": + if m.table.TotalRows() == 0 { + break + } + selectedRowId := m.table.HighlightedRow().Data[XKaytuRowId] + for _, i := range m.optimizations.Items() { + if selectedRowId == i.GetOverviewChartRow().GetRowId() && !i.GetSkipped() && !i.GetLoading() && !i.GetLazyLoadingEnabled() { + m.optimizations.SelectItem(i) + changePageCmd = m.app.ChangePage(Page_Preferences) + m.clearScreen = true + break + } + } + case "P": + if m.table.TotalRows() == 0 { + break + } + m.optimizations.SelectItem(nil) + changePageCmd = m.app.ChangePage(Page_Preferences) + m.clearScreen = true + case "r": + start, end := m.table.VisibleIndices() + for _, i := range m.optimizations.Items()[start : end+1] { + if !i.GetSkipped() && i.GetLazyLoadingEnabled() { + i.LazyLoadingEnabled = false + i.Loading = true + m.optimizations.SendItem(i) + m.optimizations.ReEvaluate(i.GetOverviewChartRow().GetRowId(), i.GetPreferences()) + } + } + + case "right": + m.table = m.table.ScrollRight() + case "left": + m.table = m.table.ScrollLeft() + case "enter": + if m.table.TotalRows() == 0 { + break + } + + selectedRowId := m.table.HighlightedRow().Data[XKaytuRowId] + for _, i := range m.optimizations.Items() { + if selectedRowId == i.GetOverviewChartRow().GetRowId() && !i.GetSkipped() && !i.GetLoading() && !i.GetLazyLoadingEnabled() { + m.optimizations.SelectItem(i) + changePageCmd = m.app.ChangePage(Page_ResourceDetails) + break + } else if selectedRowId == i.GetOverviewChartRow().GetRowId() && !i.GetLoading() && i.GetLazyLoadingEnabled() { + i.LazyLoadingEnabled = false + i.Loading = true + m.optimizations.SendItem(i) + m.optimizations.ReEvaluate(i.GetOverviewChartRow().GetRowId(), i.GetPreferences()) + } + } + } + } + + var cmd tea.Cmd + m.table, cmd = m.table.Update(msg) + + if changePageCmd != nil { + cmd = tea.Batch(cmd, changePageCmd) + } + newStatusBar, _ := m.statusBar.Update(msg) + m.statusBar = newStatusBar.(StatusBarView) + + m.table = m.table.WithPageSize(m.GetHeight() - (7 + m.statusBar.Height())).WithMaxTotalWidth(m.GetWidth()) + + return m, cmd +} + +func (m PluginCustomOverviewPage) View() string { + return "" +} + +func (m PluginCustomOverviewPage) SetApp(app *App) PluginCustomOverviewPage { + m.app = app + return m +} + +func (m PluginCustomOverviewPage) SetResponsiveView(rv responsive.ResponsiveViewInterface) Page { + m.ResponsiveView = rv.(responsive.ResponsiveView) + return m +} diff --git a/view/page_preferences.go b/view/page_preferences.go index 3893c22..8bbf4a1 100644 --- a/view/page_preferences.go +++ b/view/page_preferences.go @@ -17,7 +17,7 @@ type ( errMsg error ) -type PreferencesPage struct { +type PreferencesPage[T golang.OptimizationItem | golang.ChartOptimizationItem] struct { focused int err error @@ -27,28 +27,35 @@ type PreferencesPage struct { visibleStartIdx int helpController *controller.Help - optimizations *controller.Optimizations + optimizations *controller.Optimizations[T] statusBar StatusBarView responsive.ResponsiveView } -func NewPreferencesConfiguration( +func NewPreferencesConfiguration[T golang.OptimizationItem | golang.ChartOptimizationItem]( helpController *controller.Help, - optimizations *controller.Optimizations, + optimizations *controller.Optimizations[T], statusBar StatusBarView, -) PreferencesPage { - return PreferencesPage{ +) PreferencesPage[T] { + return PreferencesPage[T]{ helpController: helpController, optimizations: optimizations, statusBar: statusBar, } } -func (m PreferencesPage) OnOpen() Page { +func (m PreferencesPage[T]) OnOpen() Page { m.visibleStartIdx = 0 var preferences []*golang.PreferenceItem if selectedItem := m.optimizations.SelectedItem(); selectedItem != nil { - preferences = selectedItem.Preferences + switch any(selectedItem).(type) { + case *golang.OptimizationItem: + selectedItem := any(selectedItem).(*golang.OptimizationItem) + preferences = selectedItem.Preferences + case *golang.ChartOptimizationItem: + selectedItem := any(selectedItem).(*golang.ChartOptimizationItem) + preferences = selectedItem.GetPreferences() + } } else { preferences = preferences2.DefaultPreferences() } @@ -84,41 +91,65 @@ func (m PreferencesPage) OnOpen() Page { return m } -func (m PreferencesPage) OnClose() Page { +func (m PreferencesPage[T]) OnClose() Page { selectedItem := m.optimizations.SelectedItem() if selectedItem == nil { for _, selectedItem := range m.optimizations.Items() { - if selectedItem.Skipped || selectedItem.LazyLoadingEnabled { - continue - } - - var prefs []*golang.PreferenceItem - for _, item := range m.items { - prefs = append(prefs, item.pref) + switch castedSelectedItem := any(selectedItem).(type) { + case *golang.OptimizationItem: + if castedSelectedItem.Skipped || castedSelectedItem.LazyLoadingEnabled { + continue + } + var prefs []*golang.PreferenceItem + for _, item := range m.items { + prefs = append(prefs, item.pref) + } + castedSelectedItem.Preferences = prefs + castedSelectedItem.Loading = true + var a = any(castedSelectedItem).(T) + m.optimizations.SendItem(&a) + m.optimizations.ReEvaluate(castedSelectedItem.Id, prefs) + case *golang.ChartOptimizationItem: + if castedSelectedItem.GetSkipped() || castedSelectedItem.GetLazyLoadingEnabled() { + continue + } + var prefs []*golang.PreferenceItem + for _, item := range m.items { + prefs = append(prefs, item.pref) + } + castedSelectedItem.Preferences = prefs + castedSelectedItem.Loading = true + var a = any(castedSelectedItem).(T) + m.optimizations.SendItem(&a) + m.optimizations.ReEvaluate(castedSelectedItem.GetOverviewChartRow().GetRowId(), prefs) } - selectedItem.Preferences = prefs - selectedItem.Loading = true - m.optimizations.SendItem(selectedItem) - m.optimizations.ReEvaluate(selectedItem.Id, prefs) } } else { var prefs []*golang.PreferenceItem for _, item := range m.items { prefs = append(prefs, item.pref) } - selectedItem.Preferences = prefs - selectedItem.Loading = true - m.optimizations.SendItem(selectedItem) - m.optimizations.ReEvaluate(selectedItem.Id, prefs) + switch castedSelectedItem := any(selectedItem).(type) { + case *golang.OptimizationItem: + castedSelectedItem.Preferences = prefs + castedSelectedItem.Loading = true + m.optimizations.SendItem(selectedItem) + m.optimizations.ReEvaluate(castedSelectedItem.Id, prefs) + case *golang.ChartOptimizationItem: + castedSelectedItem.Preferences = prefs + castedSelectedItem.Loading = true + m.optimizations.SendItem(selectedItem) + m.optimizations.ReEvaluate(castedSelectedItem.GetOverviewChartRow().GetRowId(), prefs) + } } return m } -func (m PreferencesPage) Init() tea.Cmd { +func (m PreferencesPage[T]) Init() tea.Cmd { return textinput.Blink } -func (m PreferencesPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) { +func (m PreferencesPage[T]) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.KeyMsg: switch msg.Type { @@ -162,7 +193,7 @@ func (m PreferencesPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, cmd } -func (m PreferencesPage) View() string { +func (m PreferencesPage[T]) View() string { builder := strings.Builder{} builder.WriteString(style.SvcDisable.Render("Configure your preferences:")) @@ -204,7 +235,7 @@ func (m PreferencesPage) View() string { return builder.String() } -func (m *PreferencesPage) ChangeService(svc string) { +func (m *PreferencesPage[T]) ChangeService(svc string) { if svc == "All" { for _, i := range m.items { i.hidden = false @@ -242,7 +273,7 @@ func numberValidator(s string) error { return nil } -func (m *PreferencesPage) fixVisibleStartIdx() { +func (m *PreferencesPage[T]) fixVisibleStartIdx() { for m.focused < m.visibleStartIdx { m.visibleStartIdx-- } @@ -253,14 +284,14 @@ func (m *PreferencesPage) fixVisibleStartIdx() { } } -func (m *PreferencesPage) nextInput() { +func (m *PreferencesPage[T]) nextInput() { m.focused = (m.focused + 1) % len(m.items) if m.items[m.focused].hidden { m.nextInput() } } -func (m *PreferencesPage) prevInput() { +func (m *PreferencesPage[T]) prevInput() { m.focused-- // Wrap around if m.focused < 0 { @@ -271,7 +302,7 @@ func (m *PreferencesPage) prevInput() { } } -func (m PreferencesPage) SetResponsiveView(rv responsive.ResponsiveViewInterface) Page { +func (m PreferencesPage[T]) SetResponsiveView(rv responsive.ResponsiveViewInterface) Page { m.ResponsiveView = rv.(responsive.ResponsiveView) return m } diff --git a/view/page_resource_details.go b/view/page_resource_details.go index 11d0288..17fd30d 100644 --- a/view/page_resource_details.go +++ b/view/page_resource_details.go @@ -41,13 +41,13 @@ type ResourceDetailsPage struct { detailTableHasFocus bool helpController *controller.Help - optimizationsController *controller.Optimizations + optimizationsController *controller.Optimizations[golang.OptimizationItem] statusBar StatusBarView app *App responsive.ResponsiveView } -func ExtractProperties(item *golang.OptimizationItem) map[string]Rows { +func (m ResourceDetailsPage) ExtractProperties(item *golang.OptimizationItem) map[string]Rows { res := map[string]Rows{} for _, dev := range item.Devices { rows := Rows{} @@ -80,7 +80,7 @@ func ExtractProperties(item *golang.OptimizationItem) map[string]Rows { } func NewOptimizationDetailsView( - optimizationsController *controller.Optimizations, + optimizationsController *controller.Optimizations[golang.OptimizationItem], helpController *controller.Help, statusBar StatusBarView, ) ResourceDetailsPage { @@ -153,7 +153,7 @@ func (m ResourceDetailsPage) OnOpen() Page { Focused(true). WithPageSize(len(deviceRows)). WithBaseStyle(style.ActiveStyleBase).BorderRounded() - m.deviceProperties = ExtractProperties(item) + m.deviceProperties = m.ExtractProperties(item) m.detailTableHasFocus = false m.selectedDevice = "" m.helpController.SetKeyMap([]string{ diff --git a/view/page_resource_details_plugin_custom.go b/view/page_resource_details_plugin_custom.go new file mode 100644 index 0000000..425a717 --- /dev/null +++ b/view/page_resource_details_plugin_custom.go @@ -0,0 +1,257 @@ +package view + +import ( + "fmt" + tea "github.com/charmbracelet/bubbletea" + "github.com/evertras/bubble-table/table" + "github.com/kaytu-io/kaytu/controller" + "github.com/kaytu-io/kaytu/pkg/plugin/proto/src/golang" + "github.com/kaytu-io/kaytu/pkg/style" + "github.com/kaytu-io/kaytu/view/responsive" + "github.com/muesli/reflow/wordwrap" + "strings" +) + +const XKaytuRowId = "x_kaytu_row_id" + +type RowsWithId []RowWithId + +func (r RowsWithId) ToTableRows() []table.Row { + var rows []table.Row + for _, row := range r { + rows = append(rows, row.ToTableRow()) + } + return rows +} + +type RowWithId struct { + ID string + Row map[string]string +} + +func (r RowWithId) ToTableRow() table.Row { + data := table.RowData{} + for k, v := range r.Row { + data[k] = v + } + data[XKaytuRowId] = r.ID + return table.NewRow(data) +} + +type PluginCustomResourceDetailsPage struct { + chartDefinition *golang.ChartDefinition + + item *golang.ChartOptimizationItem + deviceTable table.Model + detailTable table.Model + deviceProperties map[string]Rows + selectedDevice string + detailTableHasFocus bool + + helpController *controller.Help + optimizationsController *controller.Optimizations[golang.ChartOptimizationItem] + statusBar StatusBarView + app *App + responsive.ResponsiveView +} + +func (m PluginCustomResourceDetailsPage) ExtractProperties(item *golang.ChartOptimizationItem) map[string]Rows { + res := map[string]Rows{} + for devId, dev := range item.GetDevicesProperties() { + rows := Rows{} + + for _, prop := range dev.Properties { + if !strings.HasPrefix(prop.Key, " ") { + prop.Key = style.Bold.Render(prop.Key) + } + rows = append(rows, Row{ + prop.Key, + prop.Current, + prop.Average, + prop.Recommended, + }) + } + res[devId] = rows + } + + for deviceID, rows := range res { + for idx, row := range rows { + if row[1] != row[3] { + row[1] = style.ChangeFrom.Render(row[1]) + row[3] = style.ChangeTo.Render(row[3]) + } + rows[idx] = row + } + res[deviceID] = rows + } + return res +} + +func NewPluginCustomOptimizationDetailsView( + chartDefinition *golang.ChartDefinition, + optimizationsController *controller.Optimizations[golang.ChartOptimizationItem], + helpController *controller.Help, + statusBar StatusBarView, +) PluginCustomResourceDetailsPage { + return PluginCustomResourceDetailsPage{ + chartDefinition: chartDefinition, + helpController: helpController, + optimizationsController: optimizationsController, + statusBar: statusBar, + } +} + +func (m PluginCustomResourceDetailsPage) OnOpen() Page { + item := m.optimizationsController.SelectedItem() + + var deviceColumns []table.Column + for _, column := range m.chartDefinition.GetColumns() { + deviceColumns = append(deviceColumns, table.NewColumn(column.GetId(), column.GetName(), int(column.GetWidth()))) + } + + deviceRows := RowsWithId{} + for _, deviceChartRow := range item.GetDevicesChartRows() { + rowValues := make(map[string]string) + for key, value := range deviceChartRow.GetValues() { + rowValues[key] = value.GetValue() + } + + deviceRows = append(deviceRows, RowWithId{ + ID: deviceChartRow.GetRowId(), + Row: rowValues, + }) + } + + days := "7" + for _, p := range item.Preferences { + if p.Key == "ObservabilityTimePeriod" && p.Value != nil { + days = p.Value.Value + } + } + detailColumns := []table.Column{ + table.NewColumn("0", "", 30), + table.NewColumn("1", "Current", 30), + table.NewColumn("2", fmt.Sprintf("%s day usage", days), 15), + table.NewColumn("3", "Recommendation", 30), + } + + m.item = item + m.detailTable = table.New(detailColumns). + WithPageSize(1). + WithHorizontalFreezeColumnCount(1). + WithBaseStyle(style.Base).BorderRounded() + m.deviceTable = table.New(deviceColumns). + WithRows(deviceRows.ToTableRows()). + WithHighlightedRow(0). + WithHorizontalFreezeColumnCount(1). + Focused(true). + WithPageSize(len(deviceRows)). + WithBaseStyle(style.ActiveStyleBase).BorderRounded() + m.deviceProperties = m.ExtractProperties(item) + m.detailTableHasFocus = false + m.selectedDevice = "" + m.helpController.SetKeyMap([]string{ + "↑/↓: move", + "←/→: scroll in the table", + "enter: switch to device detail table", + "esc: back to optimizations list", + "q/ctrl+c: exit", + }) + return m +} +func (m PluginCustomResourceDetailsPage) OnClose() Page { + return m +} +func (m PluginCustomResourceDetailsPage) Init() tea.Cmd { + return nil +} + +func (m PluginCustomResourceDetailsPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + var cmd, detailCMD tea.Cmd + switch msg := msg.(type) { + case tea.WindowSizeMsg: + m.detailTable = m.detailTable.WithMaxTotalWidth(m.GetWidth()) + m.deviceTable = m.deviceTable.WithMaxTotalWidth(m.GetWidth()) + case tea.KeyMsg: + switch msg.String() { + case "q": + return m, tea.Quit + case "enter": + m.detailTableHasFocus = true + m.app.SetIgnoreEsc(true) + m.deviceTable = m.deviceTable.WithBaseStyle(style.Base) + m.detailTable = m.detailTable.WithBaseStyle(style.ActiveStyleBase).Focused(true).WithHighlightedRow(0) + case "right": + if m.detailTableHasFocus { + m.detailTable = m.detailTable.ScrollRight() + } else { + m.deviceTable = m.deviceTable.ScrollRight() + } + case "left": + if m.detailTableHasFocus { + m.detailTable = m.detailTable.ScrollLeft() + } else { + m.deviceTable = m.deviceTable.ScrollLeft() + } + case "esc": + m.app.SetIgnoreEsc(false) + if m.detailTableHasFocus { + m.detailTableHasFocus = false + m.detailTable = m.detailTable.Focused(false).WithBaseStyle(style.Base) + m.deviceTable = m.deviceTable.Focused(true).WithBaseStyle(style.ActiveStyleBase) + } + default: + if m.detailTableHasFocus { + m.detailTable, cmd = m.detailTable.Update(msg) + } else { + m.deviceTable, cmd = m.deviceTable.Update(msg) + } + } + default: + if m.detailTableHasFocus { + m.detailTable, cmd = m.detailTable.Update(msg) + } else { + m.deviceTable, cmd = m.deviceTable.Update(msg) + } + } + + if m.deviceTable.HighlightedRow().Data["0"] != nil && m.selectedDevice != m.deviceTable.HighlightedRow().Data["0"] { + m.selectedDevice = m.deviceTable.HighlightedRow().Data["0"].(string) + + m.detailTable = m.detailTable.WithRows(m.deviceProperties[m.selectedDevice].ToTableRows()) + } + + lineCount := strings.Count(wordwrap.String(m.item.GetDescription(), m.GetWidth()), "\n") + 1 + deviceTableHeight := 7 + detailsTableHeight := 7 + + for lineCount+deviceTableHeight+detailsTableHeight+m.statusBar.Height() < m.GetHeight() { + if deviceTableHeight-6 < len(m.deviceProperties) && deviceTableHeight < detailsTableHeight { + deviceTableHeight++ + } else { + detailsTableHeight++ + } + } + m.deviceTable = m.deviceTable.WithPageSize(deviceTableHeight - 6).WithMaxTotalWidth(m.GetWidth()) + m.detailTable = m.detailTable.WithPageSize(detailsTableHeight - 6).WithMaxTotalWidth(m.GetWidth()) + newStatusBar, _ := m.statusBar.Update(msg) + m.statusBar = newStatusBar.(StatusBarView) + + return m, tea.Batch(detailCMD, cmd) +} + +func (m PluginCustomResourceDetailsPage) View() string { + return m.deviceTable.View() + "\n" + + wordwrap.String(m.item.GetDescription(), m.GetWidth()) + "\n" + + m.detailTable.View() + "\n" + + m.statusBar.View() +} + +func (m PluginCustomResourceDetailsPage) SetResponsiveView(rv responsive.ResponsiveViewInterface) Page { + m.ResponsiveView = rv.(responsive.ResponsiveView) + return m +} +func (m PluginCustomResourceDetailsPage) SetApp(app *App) PluginCustomResourceDetailsPage { + m.app = app + return m +}