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 9 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
89 changes: 89 additions & 0 deletions doc/user/ngctl_guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@

# Overview
ngctl is a terminal cmd tool for nebula-operator, it has the following commands:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this better? for nebula-operator sounds like management nebula-operator.

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 kubernetes context and namespace
Copy link
Contributor

@veezhang veezhang Jul 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thanks this is just specify namespace, and don't support specify kubernetes context now.

Please remove the kubernetes context as well as in go source file.

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

# You can also use 'use' command to specify a nebula cluster.
use nebula
ngctl list pod

# 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
```

203 changes: 203 additions & 0 deletions pkg/ngctl/cmd/check/check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
/*
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`)
)

const resourceType = "nebulacluster"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also need in 'list.go', share it?


type CheckOptions struct {
Namespace string
NebulaClusterName string
ResourceType string
AllNamespaces bool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused


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

if o.NebulaClusterName, err = f.GetNebulaClusterName(); err != nil && !cmdutil.IsErNotSpecified(err) {
return err
}

if o.Namespace, err = f.GetNamespace(); err != nil {
return err
}

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

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.")
}

if o.ResourceType == "" {
o.ResourceType = resourceType
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is need to check the o.ResourceType ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If user don't specify the resourceType, we can use "nebulacluster" as a default type

return nil
}

// RunCheck executes check command
func (o *CheckOptions) RunCheck() error {
switch o.ResourceType {
case resourceType, "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