Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ngctl: add check command and doc #39

Merged
merged 12 commits into from
Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions doc/user/ngctl_guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@

# Overview
ngctl is a terminal cmd tool for Nebula Graph managed by nebula-operator, it has the following commands:
- [ngctl use](#ngctl-use)
- [ngctl console](#ngctl-console)
- [ngctl list](#ngctl-list)
- [ngctl check](#ngctl-check)
- [ngctl info](#ngctl-info)

## ngctl use
`ngctl use` specify a nebula cluster to use. By using a certain cluster, you may omit --nebulacluster option in many control commands.

```
Examples:
# specify a nebula cluster to use
ngctl use demo-cluster

# specify the cluster name and namespace
ngctl use demo-cluster -n test-system
```
## ngctl console
`ngctl console` create a nebula-console pod and connect to the specified nebula cluster.

```
Examples:
# open console to the current nebula cluster, which is set by 'ngctl use' command
ngctl console

# Open console to the specified nebula cluster
ngctl console --nebulacluster=nebula
```
## ngctl list
`ngctl list` list nebula clusters or there sub resources. Its usage is the same as `kubectl get`, but only resources related to nbuela cluster are displayed.
```
Examples:
# List all nebula clusters.
ngctl list

# List all nebula clusters in all namespaces.
ngctl list -A

# List all nebula clusters with json format.
ngctl list -o json

# List nebula cluster sub resources with specified cluster name.
ngctl list pod --nebulacluster=nebula

# Return only the metad's phase value of the specified pod.
ngctl list -o template --template="{{.status.graphd.phase}}" NAME

# List image information in custom columns.
ngctl list -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,IMAGE:.spec.graphd.image
```

## ngctl check
`ngctl check` check whether the specified nebula cluster resources are ready. Command will print the error message from nebula cluster resource conditions, help you locate the reason quickly.

```
Examples:
# check whether the specified nebula cluster is ready
ngctl check

# check specified nebula cluster pods
ngctl check pods --nebulacluster=nebula
```

## ngctl info
`ngctl info` get current nebula cluster information, the cluster is set by 'ngctl use' command or use `--nebulacluster` flag.

```Examples:
# get current nebula cluster information, which is set by 'ngctl use' command
ngctl info

# get current nebula cluster information, which is set by '--nebulacluster' flag
ngctl info --nebulacluster=nebula
```
## ngctl version
`nfgctl version` print the cli and nebula operator version

```bash
Examples:
# Print the cli and nebula operator version
ngctl version
```

195 changes: 195 additions & 0 deletions pkg/ngctl/cmd/check/check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
/*
Copyright 2021 Vesoft Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package check

import (
"bytes"
"context"
"text/tabwriter"

"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/kubectl/pkg/util/templates"
"sigs.k8s.io/controller-runtime/pkg/client"

appsv1alpha1 "github.com/vesoft-inc/nebula-operator/apis/apps/v1alpha1"
"github.com/vesoft-inc/nebula-operator/pkg/label"
cmdutil "github.com/vesoft-inc/nebula-operator/pkg/ngctl/cmd/util"
"github.com/vesoft-inc/nebula-operator/pkg/ngctl/cmd/util/ignore"
)

var (
checkLong = templates.LongDesc(`
Check whether the specified nebula cluster resources are ready.`)

checkExample = templates.Examples(`
# check whether the specified nebula cluster is ready
ngctl check

# check specified nebula cluster pods
ngctl check pods --nebulacluster=nebula`)
)

type CheckOptions struct {
Namespace string
NebulaClusterName string
ResourceType string

runtimeCli client.Client
genericclioptions.IOStreams
}

func NewCheckOptions(streams genericclioptions.IOStreams) *CheckOptions {
return &CheckOptions{
IOStreams: streams,
}
}

// NewCmdCheck returns a cobra command for check whether nebula cluster resources are ready
func NewCmdCheck(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
o := NewCheckOptions(ioStreams)

cmd := &cobra.Command{
Use: "check",
Short: "check whether nebula cluster resources are ready",
Long: checkLong,
Example: checkExample,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(f, args))
cmdutil.CheckErr(o.Validate(cmd))
cmdutil.CheckErr(o.RunCheck())
},
}

f.AddFlags(cmd)
return cmd
}

// Complete completes all the required options
func (o *CheckOptions) Complete(f cmdutil.Factory, args []string) error {
var err error

o.NebulaClusterName, o.Namespace, err = f.GetNebulaClusterNameAndNamespace(true, nil)
if err != nil && !cmdutil.IsErNotSpecified(err) {
return err
}

if len(args) > 0 {
o.ResourceType = args[0]
} else {
o.ResourceType = cmdutil.NebulaClusterResourceType
}

o.runtimeCli, err = f.ToRuntimeClient()
if err != nil {
return err
}

return nil
}

// Validate validates the provided options
func (o *CheckOptions) Validate(cmd *cobra.Command) error {
if o.NebulaClusterName == "" {
return cmdutil.UsageErrorf(cmd, "using 'ngctl use' or '--nebulacluster' to set nebula cluster first.")
}

return nil
}

// RunCheck executes check command
func (o *CheckOptions) RunCheck() error {
switch o.ResourceType {
case cmdutil.NebulaClusterResourceType, "nebulaclusters", "nc":
{
str, err := o.CheckNebulaCluster()
if err != nil {
return err
}
ignore.Fprintf(o.Out, "%s\n", str)
}
case "pod", "pods":
{
str, err := o.CheckPods()
if err != nil {
return err
}
ignore.Fprintf(o.Out, "%s\n", str)
}
}

return nil
}

func (o *CheckOptions) CheckNebulaCluster() (string, error) {
var nc appsv1alpha1.NebulaCluster
key := client.ObjectKey{Namespace: o.Namespace, Name: o.NebulaClusterName}
if err := o.runtimeCli.Get(context.TODO(), key, &nc); err != nil {
return "", err
}
for _, cond := range nc.Status.Conditions {
if cond.Type == appsv1alpha1.NebulaClusterReady {
return cond.Message, nil
}
}
return "", nil
}

func (o *CheckOptions) CheckPods() (string, error) {
selector, err := label.New().Cluster(o.NebulaClusterName).Selector()
if err != nil {
return "", err
}

var pods corev1.PodList
listOptions := client.ListOptions{
LabelSelector: selector,
Namespace: o.Namespace,
}
if err := o.runtimeCli.List(context.TODO(), &pods, &listOptions); err != nil {
return "", err
}

allWork := true
tw := new(tabwriter.Writer)
buf := &bytes.Buffer{}
tw.Init(buf, 0, 8, 4, ' ', 0)

ignore.Fprintf(tw, "Trouble Pods:\n")
ignore.Fprintf(tw, "\tPodName\tPhase\tConditionType\tMessage\n")
ignore.Fprintf(tw, "\t-------\t------\t-------------\t-------\n")

for i := range pods.Items {
if pods.Items[i].Status.Phase != corev1.PodRunning {
allWork = false
for _, cond := range pods.Items[i].Status.Conditions {
if cond.Status != corev1.ConditionTrue {
ignore.Fprintf(tw, "\t%s", pods.Items[i].Name)
ignore.Fprintf(tw, "\t%s\t%s\t%s\n", pods.Items[i].Status.Phase, cond.Type, cond.Message)
}
}
}
}

_ = tw.Flush()

if allWork {
return "All pods are running", nil
}
return buf.String(), nil
}
Loading