Skip to content

Commit

Permalink
Add command to generate User-CLI.md and reorganize generate cmds
Browse files Browse the repository at this point in the history
  • Loading branch information
Xenorith committed Sep 13, 2023
1 parent fc7971c commit 3b7604d
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,26 @@ import (
"alluxio.org/cli/env"
)

var Docs = &DocsCommand{
var DocTables = &DocTablesCommand{
BaseJavaCommand: &env.BaseJavaCommand{
CommandName: "docs",
CommandName: "doc-tables",
JavaClassName: "alluxio.cli.DocGenerator",
ShellJavaOpts: fmt.Sprintf(env.JavaOptFormat, env.ConfAlluxioLoggerType, "Console"),
},
}

type DocsCommand struct {
type DocTablesCommand struct {
*env.BaseJavaCommand
}

func (c *DocsCommand) Base() *env.BaseJavaCommand {
func (c *DocTablesCommand) Base() *env.BaseJavaCommand {
return c.BaseJavaCommand
}

func (c *DocsCommand) ToCommand() *cobra.Command {
func (c *DocTablesCommand) ToCommand() *cobra.Command {
cmd := c.Base().InitRunJavaClassCmd(&cobra.Command{
Use: Docs.CommandName,
Short: "Generate docs automatically.",
Use: DocTables.CommandName,
Short: "Generate configuration and metric tables used in documentation",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return c.Run(args)
Expand All @@ -47,6 +47,6 @@ func (c *DocsCommand) ToCommand() *cobra.Command {
return cmd
}

func (c *DocsCommand) Run(args []string) error {
func (c *DocTablesCommand) Run(args []string) error {
return c.Base().Run(args)
}
29 changes: 27 additions & 2 deletions cli/src/alluxio.org/cli/cmd/generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,37 @@ package generate

import (
"alluxio.org/cli/env"
"github.com/palantir/stacktrace"
"github.com/spf13/cobra"
)

var Service = &env.Service{
Name: "generate",
Description: "Generate docs automatically if one doesn't exist.",
Description: "Generate files used in documentation",
Commands: []env.Command{
Docs,
&DocsCommand{},
DocTables,
UserCliDoc,
},
}

type DocsCommand struct{}

func (c *DocsCommand) ToCommand() *cobra.Command {
return &cobra.Command{
Use: DocTables.CommandName,
Short: "Generate all documentation files",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
for _, c := range []env.Command{
UserCliDoc,
DocTables,
} {
if err := c.ToCommand().RunE(cmd, args); err != nil {
return stacktrace.Propagate(err, "error running %v", c.ToCommand().Use)
}
}
return nil
},
}
}
159 changes: 159 additions & 0 deletions cli/src/alluxio.org/cli/cmd/generate/user_cli.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package generate

import (
"bufio"
"fmt"
"io"
"os"
"path/filepath"
"strings"

"github.com/palantir/stacktrace"
"github.com/spf13/cobra"
"github.com/spf13/pflag"

"alluxio.org/cli/env"
)

var UserCliDoc = &UserCliCommand{}

type UserCliCommand struct{}

func (c *UserCliCommand) ToCommand() *cobra.Command {
return &cobra.Command{
Use: "user-cli",
Short: "Generate content for `operation/User-CLI.md`",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
var rootCmd *cobra.Command
for rootCmd = cmd; rootCmd.HasParent(); rootCmd = rootCmd.Parent() {
}

f, err := os.Create(filepath.Join("docs", "en", "operation", "User-CLI.md"))
if err != nil {
return stacktrace.Propagate(err, "error creating output file")
}
defer f.Close()
w := bufio.NewWriter(f)
fmt.Fprintln(w,
`---
layout: global
title: User Command Line Interface
---
[comment]: # (This is a generated file created by running command "bin/alluxio generate user-cli")
[comment]: # (The command parses the golang command definitions and descriptions to generate the markdown in this file)
Alluxio's command line interface provides user access to various operations, such as:
- Start or stop processes
- Filesystem operations
- Administrative commands`)
fmt.Fprintln(w, "Invoke the executable to view the possible subcommands:")
fmt.Fprintln(w, "```shell")
fmt.Fprintln(w, "$ ./bin/alluxio")
fmt.Fprintln(w, rootCmd.UsageString())
fmt.Fprintln(w, "```")
fmt.Fprintln(w)
fmt.Fprintln(w, "To set JVM system properties as part of the command, set the `-D` flag in the form of `-Dproperty=value`.")
fmt.Fprintln(w)
fmt.Fprintln(w, "To attach debugging java options specified by `$ALLUXIO_USER_ATTACH_OPTS`, set the `--attach-debug` flag")
fmt.Fprintln(w)
fmt.Fprintln(w, "Note that, as a part of Alluxio deployment, the Alluxio shell will also take the configuration in `${ALLUXIO_HOME}/conf/alluxio-site.properties` when it is run from Alluxio installation at `${ALLUXIO_HOME}`.")
fmt.Fprintln(w)

for _, serviceCmd := range rootCmd.Commands() {
if serviceCmd.Name() == "help" {
// help is a built in command from the library. avoid documenting it
continue
}
fmt.Fprint(w, "## ")
fmt.Fprintln(w, serviceCmd.Name())

desc := serviceCmd.Short
if serviceCmd.Long != "" {
desc = serviceCmd.Long
}
fmt.Fprintln(w, desc)
fmt.Fprintln(w)

for _, opCmd := range serviceCmd.Commands() {
printCommandDocs(serviceCmd.Name(), opCmd, w)
}
}
w.Flush()
return nil
},
}
}

func printCommandDocs(serviceName string, opCmd *cobra.Command, w io.Writer) {
fmt.Fprintln(w, "###", serviceName, opCmd.Name())

// collect relevant flags defined for the command
inheritedFlags := opCmd.InheritedFlags()
definedFlags := pflag.NewFlagSet(fmt.Sprintf("%v_%v", serviceName, opCmd.Name()), pflag.ContinueOnError)
opCmd.Flags().VisitAll(func(f *pflag.Flag) {
if f.Hidden {
return
}
if f.Name == env.AttachDebugName || f.Name == env.JavaOptsName {
return
}
if inheritedFlags.Lookup(f.Name) == nil {
definedFlags.AddFlag(f)
}
})
if definedFlags.HasFlags() {
fmt.Fprintf(w, "Usage: `%v`\n\n", opCmd.UseLine())
} else {
// remove the [flags] part of the usage as there are no flags to mention
fmt.Fprintf(w, "Usage: `%v`\n\n", strings.Replace(opCmd.UseLine(), " [flags]", "", 1))
}

desc := opCmd.Short
if opCmd.Long != "" {
desc = opCmd.Long
}
fmt.Fprintln(w, desc)
fmt.Fprintln(w)

if definedFlags.HasFlags() {
fmt.Fprintln(w, "Flags:")
definedFlags.VisitAll(func(f *pflag.Flag) {
fmt.Fprintf(w, "- `--%v`", f.Name)
if f.Shorthand != "" {
fmt.Fprintf(w, ",`-%v`", f.Shorthand)
}
_, required := f.Annotations[cobra.BashCompOneRequiredFlag]
_, usage := pflag.UnquoteUsage(f)

// prepend the flag description with "(Required)" if required
// print default value if flag is not required
var requiredPrefix, defVal string
if required {
requiredPrefix = "(Required) "
} else {
v := f.DefValue
if f.Value.Type() == "string" {
// add quotes for string flags
v = fmt.Sprintf("%q", defVal)
}
defVal = fmt.Sprintf(" (Default: %v)", v)
}
fmt.Fprintf(w, ": %v%v%v\n", requiredPrefix, usage, defVal)

})
fmt.Fprintln(w)
}

if opCmd.HasExample() {
fmt.Fprintln(w, "Examples:")
for _, ex := range strings.Split(opCmd.Example, "\n\n") {
fmt.Fprintln(w, "```shell")
fmt.Fprintln(w, ex)
fmt.Fprintln(w, "```")
fmt.Fprintln(w)
}
fmt.Fprintln(w)
}
}
9 changes: 7 additions & 2 deletions cli/src/alluxio.org/cli/env/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,14 @@ type BaseJavaCommand struct {
ShellJavaOpts string // default java opts encoded as part of the specific command
}

const (
AttachDebugName = "attach-debug"
JavaOptsName = "java-opts"
)

func (c *BaseJavaCommand) InitRunJavaClassCmd(cmd *cobra.Command) *cobra.Command {
cmd.Flags().BoolVar(&c.DebugMode, "attach-debug", false, fmt.Sprintf("True to attach debug opts specified by $%v", ConfAlluxioUserAttachOpts.EnvVar))
cmd.Flags().StringSliceVarP(&c.InlineJavaOpts, "java-opts", "D", nil, `Alluxio properties to apply, ex. -Dkey=value`)
cmd.Flags().BoolVar(&c.DebugMode, AttachDebugName, false, fmt.Sprintf("True to attach debug opts specified by $%v", ConfAlluxioUserAttachOpts.EnvVar))
cmd.Flags().StringSliceVarP(&c.InlineJavaOpts, JavaOptsName, "D", nil, `Alluxio properties to apply, ex. -Dkey=value`)
return cmd
}

Expand Down
8 changes: 5 additions & 3 deletions cli/src/alluxio.org/cli/env/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,17 @@ func InitServiceCommandTree(rootCmd *cobra.Command) {
}

type Service struct {
Name string
Description string
Commands []Command
Name string
Description string
Documentation string
Commands []Command
}

func (s *Service) InitCommandTree(rootCmd *cobra.Command) {
cmd := &cobra.Command{
Use: s.Name,
Short: s.Description,
Long: s.Documentation,
}
rootCmd.AddCommand(cmd)

Expand Down
2 changes: 2 additions & 0 deletions cli/src/alluxio.org/cli/launch/launch.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ func Run(jarEnvVars map[bool]map[string]string, appendClasspathJars map[string]f
rootCmd := &cobra.Command{
Use: "bin/alluxio",
}
rootCmd.CompletionOptions.DisableDefaultCmd = true

const rootPathName = "rootPath"
var flagRootPath string
rootCmd.PersistentFlags().StringVar(&flagRootPath, rootPathName, "", "Path to root of Alluxio installation")
Expand Down
2 changes: 1 addition & 1 deletion cli/src/alluxio.org/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/sirupsen/logrus v1.9.0
github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.15.0
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
gopkg.in/yaml.v3 v3.0.1
Expand All @@ -23,7 +24,6 @@ require (
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.8.2 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
Expand Down

0 comments on commit 3b7604d

Please sign in to comment.