Skip to content

Commit

Permalink
feat: add json output for status and clustermesh status
Browse files Browse the repository at this point in the history
Signed-off-by: Raphaël Pinson <[email protected]>
  • Loading branch information
raphink authored and tklauser committed Feb 10, 2023
1 parent 6107190 commit 44acf5a
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 35 deletions.
59 changes: 35 additions & 24 deletions clustermesh/clustermesh.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -468,6 +469,7 @@ type Parameters struct {
ConfigOverwrites []string
Retries int
HelmValuesSecretName string
Output string
}

func (p Parameters) validateParams() error {
Expand Down Expand Up @@ -629,16 +631,16 @@ func (k *K8sClusterMesh) Enable(ctx context.Context) error {
}

type accessInformation struct {
ServiceIPs []string
ServicePort int
ClusterID string
ClusterName string
CA []byte
ClientCert []byte
ClientKey []byte
ExternalWorkloadCert []byte
ExternalWorkloadKey []byte
Tunnel string
ServiceIPs []string `json:"service_ips,omitempty"`
ServicePort int `json:"service_port,omitempty"`
ClusterID string `json:"cluster_id,omitempty"`
ClusterName string `json:"cluster_name,omitempty"`
CA []byte `json:"ca,omitempty"`
ClientCert []byte `json:"client_cert,omitempty"`
ClientKey []byte `json:"client_key,omitempty"`
ExternalWorkloadCert []byte `json:"external_workload_cert,omitempty"`
ExternalWorkloadKey []byte `json:"external_workload_key,omitempty"`
Tunnel string `json:"tunnel,omitempty"`
}

func (ai *accessInformation) etcdConfiguration() string {
Expand Down Expand Up @@ -1042,9 +1044,9 @@ func (k *K8sClusterMesh) Disconnect(ctx context.Context) error {
}

type Status struct {
AccessInformation *accessInformation
Service *corev1.Service
Connectivity *ConnectivityStatus
AccessInformation *accessInformation `json:"access_information,omitempty"`
Service *corev1.Service `json:"service,omitempty"`
Connectivity *ConnectivityStatus `json:"connectivity,omitempty"`
}

func (k *K8sClusterMesh) statusAccessInformation(ctx context.Context, log bool, getExternalWorkloadSecret bool) (*accessInformation, error) {
Expand Down Expand Up @@ -1104,23 +1106,23 @@ func (k *K8sClusterMesh) waitForDeployment(ctx context.Context) error {
}

type StatisticalStatus struct {
Min int64
Avg float64
Max int64
Min int64 `json:"min,omitempty"`
Avg float64 `json:"avg,omitempty"`
Max int64 `json:"max,omitempty"`
}

type ClusterStats struct {
Configured int
Connected int
Configured int `json:"configured,omitempty"`
Connected int `json:"connected,omitempty"`
}

type ConnectivityStatus struct {
GlobalServices StatisticalStatus
Connected StatisticalStatus
Clusters map[string]*ClusterStats
Total int64
NotReady int64
Errors status.ErrorCountMapMap
GlobalServices StatisticalStatus `json:"global_services,omitempty"`
Connected StatisticalStatus `json:"connected,omitempty"`
Clusters map[string]*ClusterStats `json:"clusters,omitempty"`
Total int64 `json:"total,omitempty"`
NotReady int64 `json:"not_ready,omitempty"`
Errors status.ErrorCountMapMap `json:"errors,omitempty"`
}

func (c *ConnectivityStatus) addError(pod, cluster string, err error) {
Expand Down Expand Up @@ -1296,6 +1298,15 @@ func (k *K8sClusterMesh) Status(ctx context.Context) (*Status, error) {

s.Connectivity, err = k.statusConnectivity(ctx)

if k.params.Output == status.OutputJSON {
jsonStatus, err := json.MarshalIndent(s, "", " ")
if err != nil {
return nil, fmt.Errorf("failed to marshal status to JSON")
}
fmt.Println(string(jsonStatus))
return s, nil
}

if s.Connectivity != nil {
if s.Connectivity.NotReady > 0 {
k.Log("⚠️ %d/%d nodes are not connected to all clusters [min:%d / avg:%.1f / max:%d]",
Expand Down
8 changes: 8 additions & 0 deletions internal/cli/cmd/clustermesh.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"github.com/cilium/cilium-cli/clustermesh"
"github.com/cilium/cilium-cli/defaults"
"github.com/cilium/cilium-cli/status"
)

func newCmdClusterMesh() *cobra.Command {
Expand Down Expand Up @@ -152,6 +153,12 @@ func newCmdClusterMeshStatus() *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
params.Namespace = namespace

if params.Output == status.OutputJSON {
// Write status log messages to stderr to make sure they don't
// clutter JSON output.
params.Writer = os.Stderr
}

cm := clustermesh.NewK8sClusterMesh(k8sClient, params)
if _, err := cm.Status(context.Background()); err != nil {
fatalf("Unable to determine status: %s", err)
Expand All @@ -163,6 +170,7 @@ func newCmdClusterMeshStatus() *cobra.Command {
cmd.Flags().BoolVar(&params.Wait, "wait", false, "Wait until status is successful")
cmd.Flags().DurationVar(&params.WaitDuration, "wait-duration", 15*time.Minute, "Maximum time to wait")
cmd.Flags().BoolVar(&params.SkipServiceCheck, "skip-service-check", false, "Do not require service IP of remote cluster to be available")
cmd.Flags().StringVarP(&params.Output, "output", "o", status.OutputSummary, "Output format. One of: json, summary")

return cmd
}
Expand Down
18 changes: 16 additions & 2 deletions internal/cli/cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ package cmd

import (
"context"
"encoding/json"
"fmt"
"os"

"github.com/spf13/cobra"

Expand All @@ -29,11 +31,22 @@ func newCmdStatus() *cobra.Command {
}

s, err := collector.Status(context.Background())
// Report the most recent status even if an error occurred.
fmt.Print(s.Format())
if err != nil {
// Report the most recent status even if an error occurred.
fmt.Fprint(os.Stderr, s.Format())
fatalf("Unable to determine status: %s", err)
}
if params.Output == status.OutputJSON {
jsonStatus, err := json.MarshalIndent(s, "", " ")
if err != nil {
// Report the most recent status even if an error occurred.
fmt.Fprint(os.Stderr, s.Format())
fatalf("Unable to marshal status to JSON: %s", err)
}
fmt.Println(string(jsonStatus))
} else {
fmt.Print(s.Format())
}
return err
},
}
Expand All @@ -43,6 +56,7 @@ func newCmdStatus() *cobra.Command {
cmd.Flags().IntVar(&params.WorkerCount,
"worker-count", status.DefaultWorkerCount,
"The number of workers to use")
cmd.Flags().StringVarP(&params.Output, "output", "o", status.OutputSummary, "Output format. One of: json, summary")

return cmd
}
3 changes: 3 additions & 0 deletions status/k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ type K8sStatusParameters struct {

// The number of workers to use.
WorkerCount int

// The output format
Output string
}

type K8sStatusCollector struct {
Expand Down
23 changes: 14 additions & 9 deletions status/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ const (
Reset = "\033[0m"
)

const (
OutputJSON = "json"
OutputSummary = "summary"
)

// MapCount is a map to count number of occurrences of a string
type MapCount map[string]int

Expand All @@ -35,10 +40,10 @@ type MapMapCount map[string]MapCount
// PodStateCount counts the number of pods in the k8s cluster
type PodsCount struct {
// All is the number of all pods in the k8s cluster
All int
All int `json:"all"`

// ByCilium is the number of all the pods in the k8s cluster
ByCilium int
ByCilium int `json:"by_cilium"`
}

// PodStateCount counts the number of pods in a particular state
Expand Down Expand Up @@ -77,29 +82,29 @@ type ErrorCountMapMap map[string]ErrorCountMap
type Status struct {
// ImageCount is a map counting the number of images in use indexed by
// the image name
ImageCount MapMapCount
ImageCount MapMapCount `json:"image_count,omitempty"`

// PhaseCount is a map counting the number of pods in each phase
// (running, failing, scheduled, ...)
PhaseCount MapMapCount
PhaseCount MapMapCount `json:"phase_count,omitempty"`

// PodState counts the number of pods matching conditions such as
// desired, ready, available, and unavailable
PodState PodStateMap
PodState PodStateMap `json:"pod_state,omitempty"`

// PodsCount is the number of pods in the k8s cluster
// all pods, and pods managed by cilium
PodsCount PodsCount
PodsCount PodsCount `json:"pods_count,omitempty"`

CiliumStatus CiliumStatusMap
CiliumStatus CiliumStatusMap `json:"cilium_status,omitempty"`

// Errors is the aggregated errors and warnings of all pods of a
// particular deployment type
Errors ErrorCountMapMap
Errors ErrorCountMapMap `json:"errors,omitempty"`

// CollectionErrors is the errors that accumulated while collecting the
// status
CollectionErrors []error
CollectionErrors []error `json:"collection_errors,omitempty"`

mutex *sync.Mutex
}
Expand Down

0 comments on commit 44acf5a

Please sign in to comment.