Skip to content

Commit

Permalink
Add custom panels for monitor cluster command (#235)
Browse files Browse the repository at this point in the history
  • Loading branch information
tmiddlet2666 authored Oct 11, 2024
1 parent 116112f commit 62e6973
Show file tree
Hide file tree
Showing 9 changed files with 309 additions and 7 deletions.
49 changes: 47 additions & 2 deletions docs/reference/99_monitor_clusters.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ NOTE: The `monitor cluster` command is currently experimental only and may be ch
* <<monitor-cluster, `cohctl monitor cluster`>> - monitors the cluster using text based UI
* <<monitor-cluster-panels, `cohctl monitor cluster --show-panels`>> - shows all available panels
* <<get-panels, `cohctl get panels`>> - displays the panels that have been created
* <<add-panel, `cohctl add panel`>> - adds a panel to the list of panels that can be displayed
* <<remove-panel, `cohctl remove panel`>> - removes a panel that has been created
[#monitor-cluster]
==== Monitor Cluster
Expand Down Expand Up @@ -183,8 +186,6 @@ Coherence CLI: 2024-05-06 11:13:59 - Monitoring cluster local (22.06.8) ESC to q
NOTE: Any of the panels or layouts that specify `cache-*` or `service-*` must have the cache or service specified using
`-C` or `-S` respectively.
[#monitor-cluster-panels]
==== Monitor Cluster Show Panels
Expand All @@ -196,6 +197,50 @@ Output:
include::../../build/_output/docs-gen/monitor_cluster_panels.adoc[tag=text]
[#get-panels]
==== Get Panels
include::../../build/_output/docs-gen/get_panels.adoc[tag=text]
[source,bash]
----
cohctl get panels
PANEL LAYOUT
caches caches:services
test caches,services:persistence
----
NOTE: Added panels cant be used by specifying the `-l` option in the `monitor cluster` command.
[#add-panel]
==== Add Panel
include::../../build/_output/docs-gen/add_panel.adoc[tag=text]
[source,bash]
----
cohctl add panel my-panel -l "caches:services,persistence"
Are you sure you want to add the panel my-panel with layout of [caches:services,persistence]? (y/n) y
panel my-panel was added with layout [caches:services,persistence]
----
NOTE: Added panels cant be used by specifying the `-l` option on `monitor cluster` command.
[#remove-panel]
==== Remove Panel
include::../../build/_output/docs-gen/remove_panel.adoc[tag=text]
[source,bash]
----
cohctl remove panel my-panel
Are you sure you want to remove the panel my-panel? (y/n) y
panel my-panel was removed
----
=== See Also
* <<docs/reference/05_clusters.adoc,Clusters>>
Expand Down
9 changes: 9 additions & 0 deletions pkg/cmd/completions.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ func completionAllProfiles(_ *cobra.Command, _ []string, _ string) ([]string, co
return profiles, cobra.ShellCompDirectiveNoFileComp
}

// completionAllPanels provides a completion function to return all panels.
func completionAllPanels(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
panels := make([]string, 0)
for _, p := range Config.Panels {
panels = append(panels, p.Name)
}
return panels, cobra.ShellCompDirectiveNoFileComp
}

// completionCaches provides a completion function to return all cache names.
func completionCaches(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
var (
Expand Down
24 changes: 20 additions & 4 deletions pkg/cmd/formatting.go
Original file line number Diff line number Diff line change
Expand Up @@ -1140,14 +1140,13 @@ func FormatDiscoveredClusters(clusters []discovery.DiscoveredCluster) string {

// FormatProfiles returns the profiles in a column formatted output.
func FormatProfiles(profiles []ProfileValue) string {
var (
profileCount = len(profiles)
)
var profileCount = len(profiles)

if profileCount == 0 {
return ""
}

table := newFormattedTable().WithHeader("PROFILE", "VALUE")
table := newFormattedTable().WithHeader("PROFILE", "VALUE").WithSortingColumn("PROFILE")

for _, value := range profiles {
table.AddRow(value.Name, value.Value)
Expand All @@ -1156,6 +1155,23 @@ func FormatProfiles(profiles []ProfileValue) string {
return table.String()
}

// FormatPanels returns the panels in a column formatted output.
func FormatPanels(panels []Panel) string {
var panelCount = len(panels)

if panelCount == 0 {
return ""
}

table := newFormattedTable().WithHeader("PANEL", "LAYOUT").WithSortingColumn("PANEL")

for _, value := range panels {
table.AddRow(value.Name, value.Layout)
}

return table.String()
}

// FormatClusterConnections returns the cluster information in a column formatted output.
func FormatClusterConnections(clusters []ClusterConnection) string {
var (
Expand Down
8 changes: 8 additions & 0 deletions pkg/cmd/monitor_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,14 @@ Use --show-panels to show all available panels.`,
padMaxHeightParam = false
}

// check for custom panel layouts added by "add panel"
if layoutParam != "" {
if l := getPanelLayout(layoutParam); l != "" {
layoutParam = l

}
}

// check for default layouts
if l, ok := defaultMap[layoutParam]; ok {
layoutParam = l
Expand Down
165 changes: 165 additions & 0 deletions pkg/cmd/panel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* Copyright (c) 2024 Oracle and/or its affiliates.
* Licensed under the Universal Permissive License v 1.0 as shown at
* https://oss.oracle.com/licenses/upl.
*/

package cmd

import (
"errors"
"fmt"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

const providePanelName = "you must provide a panel name"

var panelLayout string

// addPanelCmd represents the add profile command.
var addPanelCmd = &cobra.Command{
Use: "panel panel-name",
Short: "add a panel and layout for displaying in monitor clusters.",
Long: `The 'add panel' command adds a panel to the list of panels that can be displayed
byt the 'monitor clusters' command.`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) != 1 {
displayErrorAndExit(cmd, providePanelName)
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
var (
panelName = args[0]
err error
panels = Config.Panels
)

// validate panel name
if err = validateProfileName(panelName); err != nil {
return err
}

if len(panelLayout) == 0 {
return errors.New("you must provide a value for the panel")
}

if getPanelLayout(panelName) != "" {
return fmt.Errorf("the panel '%s' already exists", panelName)
}

if panelAlreadyExists(panelName) {
return fmt.Errorf("the panel '%s' already exists in the list of panels in monitor cluster", panelName)
}

// confirm the operation
if !confirmOperation(cmd, fmt.Sprintf("Are you sure you want to add the panel %s with layout of [%s]? (y/n) ", panelName, panelLayout)) {
return nil
}

panels = append(panels, Panel{Name: panelName, Layout: panelLayout})

viper.Set(panelsKey, panels)
err = WriteConfig()
if err != nil {
return err
}
cmd.Printf("panel %s was added with layout [%s]\n", panelName, panelLayout)
return nil
},
}

// removePanelCmd represents the remove panel command.
var removePanelCmd = &cobra.Command{
Use: "panel panel-name",
Short: "remove a panel from the list of panels",
Long: `The 'remove panel' command removes a panel from the list of panels.`,
ValidArgsFunction: completionAllPanels,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) != 1 {
displayErrorAndExit(cmd, providePanelName)
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
var (
panelName = args[0]
err error
panels = Config.Panels
)

if getPanelLayout(panelName) == "" {
return fmt.Errorf("a panel with the name %s does not exist", panelName)
}

// confirm the operation
if !confirmOperation(cmd, fmt.Sprintf("Are you sure you want to remove the panel %s? (y/n) ", panelName)) {
return nil
}

newPanels := make([]Panel, 0)

// loop though the list of panels
for _, v := range panels {
if v.Name != panelName {
newPanels = append(newPanels, v)
}
}

viper.Set(panelsKey, newPanels)
err = WriteConfig()
if err != nil {
return err
}
cmd.Printf("panel %s was removed\n", panelName)
return nil
},
}

// panelAlreadyExists returns true if the panel exists in either the default panel or
// in the list of panels
func panelAlreadyExists(panelName string) bool {
// also check for other panels
if validatePanels([]string{panelName}) == nil {
return true
}

// validate that the panel is not in the list of known default panels in the monitor cluster command
if _, ok := defaultMap[panelName]; ok {
return true
}

return false
}

// getProfilesCmd represents the get profiles command.
var getPanelsCmd = &cobra.Command{
Use: "panels",
Short: "display the panels that have been created",
Long: `The 'get panels' displays the panels that have been created.`,
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, _ []string) error {
cmd.Println(FormatPanels(Config.Panels))
return nil
},
}

func init() {
addPanelCmd.Flags().StringVarP(&panelLayout, "layout", "l", "", "panel layout")
_ = addPanelCmd.MarkFlagRequired("layout")
addPanelCmd.Flags().BoolVarP(&automaticallyConfirm, "yes", "y", false, confirmOptionMessage)

removePanelCmd.Flags().BoolVarP(&automaticallyConfirm, "yes", "y", false, confirmOptionMessage)
}

// getPanelLayout returns the layout for a given panel or "" if the panel doesn't exist.
func getPanelLayout(panelName string) string {
for _, v := range Config.Panels {
if v.Name == panelName {
return v.Layout
}
}

return ""
}
12 changes: 12 additions & 0 deletions pkg/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ const (
ignoreCertsContextKey = "ignoreInvalidCerts"
requestTimeoutKey = "requestTimeout"
defaultBytesFormatKey = "defaultBytesFormat"
defaultLayoutKey = "defaultLayout"
defaultHeapKey = "defaultHeap"
profilesKey = "profiles"
panelsKey = "panels"

confirmOptionMessage = "automatically confirm the operation"
timeoutMessage = "timeout in seconds for NS Lookup requests"
Expand Down Expand Up @@ -171,6 +173,7 @@ type CoherenceCLIConfig struct {
DefaultHeap string `json:"defaultHeap"`
UseGradle bool `json:"useGradle"`
Profiles []ProfileValue `mapstructure:"profiles"`
Panels []Panel `mapstructure:"panels"`
}

// ProfileValue describes a profile to be used for creating and starting clusters.
Expand All @@ -179,6 +182,12 @@ type ProfileValue struct {
Value string `json:"value"`
}

// Panel describes a panel and layout that can be used by the monitor cluster command.
type Panel struct {
Name string `json:"name"`
Layout string `json:"layout"`
}

// ClusterConnection describes an individual connection to a cluster.
type ClusterConnection struct {
Name string `json:"name"` // the name the user gives to the cluster connection
Expand Down Expand Up @@ -538,6 +547,7 @@ func Initialize(command *cobra.Command) *cobra.Command {
getCmd.AddCommand(getViewCachesCmd)
getCmd.AddCommand(getCachePartitionsCmd)
getCmd.AddCommand(getFederationIncomingCmd)
getCmd.AddCommand(getPanelsCmd)

// set command
command.AddCommand(setCmd)
Expand Down Expand Up @@ -572,6 +582,7 @@ func Initialize(command *cobra.Command) *cobra.Command {
// add
command.AddCommand(addCmd)
addCmd.AddCommand(addClusterCmd)
addCmd.AddCommand(addPanelCmd)

// replicate
command.AddCommand(replicateCmd)
Expand Down Expand Up @@ -618,6 +629,7 @@ func Initialize(command *cobra.Command) *cobra.Command {
removeCmd.AddCommand(removeClusterCmd)
removeCmd.AddCommand(removeSnapshotCmd)
removeCmd.AddCommand(removeProfileCmd)
removeCmd.AddCommand(removePanelCmd)

// describe
command.AddCommand(describeCmd)
Expand Down
5 changes: 5 additions & 0 deletions scripts/generate-doc-snippets.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ create_doc $DOCS_DIR/discover_clusters "${COHCTL} discover clusters --help"
create_doc $DOCS_DIR/get_cluster_config "${COHCTL} get cluster-config --help"
create_doc $DOCS_DIR/get_cluster_description "${COHCTL} get cluster-description --help"
create_doc $DOCS_DIR/monitor_cluster "${COHCTL} monitor cluster --help"
create_doc $DOCS_DIR/add_panel "${COHCTL} add panel --help"
create_doc $DOCS_DIR/get_panels "${COHCTL} get panels --help"
create_doc $DOCS_DIR/remove_panel "${COHCTL} remove panel --help"


(
echo "// # tag::text[]"
echo "----"
Expand Down
Loading

0 comments on commit 62e6973

Please sign in to comment.