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

feat: add plugin framework and mod and registry subcommands #4

Merged
merged 1 commit into from
Oct 24, 2023
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
77 changes: 77 additions & 0 deletions cmd/mod.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package cmd

import (
"github.com/spf13/cobra"
cli "github.com/urfave/cli/v2"
"kcl-lang.io/cli/pkg/version"
"kcl-lang.io/kpm/pkg/client"
kpmcmd "kcl-lang.io/kpm/pkg/cmd"
"kcl-lang.io/kpm/pkg/reporter"
)

const (
modDesc = `
This command manages the kcl module
`
modExample = ` # Init one kcl module
kcl mod init

# Push the module
kcl mod push
`
)

// NewModCmd returns the mod command.
func NewModCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "mod",
Short: "KCL module management",
Long: modDesc,
Example: modExample,
RunE: func(_ *cobra.Command, args []string) error {
return RunWithKpmMod("mod", args)
},
SilenceUsage: true,
}

return cmd
}

func RunWithKpmMod(cmd string, args []string) error {
reporter.InitReporter()
kpmcli, err := client.NewKpmClient()
if err != nil {
return err
}
app := cli.NewApp()
app.Usage = "module related functions"
app.Name = "kcl mod"
app.Version = version.GetVersionString()
app.UsageText = "kcl mod <command> [arguments]..."
app.Commands = []*cli.Command{
kpmcmd.NewInitCmd(kpmcli),
kpmcmd.NewAddCmd(kpmcli),
kpmcmd.NewPkgCmd(kpmcli),
kpmcmd.NewMetadataCmd(kpmcli),
kpmcmd.NewRunCmd(kpmcli),
kpmcmd.NewLoginCmd(kpmcli),
kpmcmd.NewLogoutCmd(kpmcli),
kpmcmd.NewPushCmd(kpmcli),
kpmcmd.NewPullCmd(kpmcli),
}
app.Flags = []cli.Flag{
&cli.BoolFlag{
Name: kpmcmd.FLAG_QUIET,
Usage: "push in vendor mode",
},
}
app.Before = func(c *cli.Context) error {
if c.Bool(kpmcmd.FLAG_QUIET) {
kpmcli.SetLogWriter(nil)
}
return nil
}
argsWithCmd := []string{cmd}
argsWithCmd = append(argsWithCmd, args...)
return app.Run(argsWithCmd)
}
70 changes: 70 additions & 0 deletions cmd/registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package cmd

import (
"github.com/spf13/cobra"
cli "github.com/urfave/cli/v2"
"kcl-lang.io/cli/pkg/version"
"kcl-lang.io/kpm/pkg/client"
kpmcmd "kcl-lang.io/kpm/pkg/cmd"
"kcl-lang.io/kpm/pkg/reporter"
)

const (
registryDesc = `
This command manages the kcl registry
`
registryExample = ` # Login the registry
kcl registry login docker.io

# Logout the registry
kcl registry logout
`
)

// NewModCmd returns the mod command.
func NewRegistryCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "registry",
Short: "KCL registry management",
Long: registryDesc,
Example: registryExample,
RunE: func(_ *cobra.Command, args []string) error {
return RunWithKpmRegistry("registry", args)
},
SilenceUsage: true,
}

return cmd
}

func RunWithKpmRegistry(cmd string, args []string) error {
reporter.InitReporter()
kpmcli, err := client.NewKpmClient()
if err != nil {
return err
}
app := cli.NewApp()
app.Usage = "registry related functions"
app.Name = "kcl registry"
app.Version = version.GetVersionString()
app.UsageText = "kcl registry <command> [arguments]..."
app.Commands = []*cli.Command{
kpmcmd.NewLoginCmd(kpmcli),
kpmcmd.NewLogoutCmd(kpmcli),
}
app.Flags = []cli.Flag{
&cli.BoolFlag{
Name: kpmcmd.FLAG_QUIET,
Usage: "push in vendor mode",
},
}
app.Before = func(c *cli.Context) error {
if c.Bool(kpmcmd.FLAG_QUIET) {
kpmcli.SetLogWriter(nil)
}
return nil
}
argsWithCmd := []string{cmd}
argsWithCmd = append(argsWithCmd, args...)
return app.Run(argsWithCmd)
}
74 changes: 71 additions & 3 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,31 +67,99 @@
// version Shows the command version
//
// ```
// #### Alias
//
// ```
// alias kcl="kcl run"
// alias kpm="kcl mod"
// ```
package cmd

import (
"fmt"
"os"
"strings"

"github.com/spf13/cobra"
"kcl-lang.io/cli/pkg/plugin"
"kcl-lang.io/cli/pkg/version"
)

const rootDesc = `The KCL Command Line Interface (CLI).
const (
cmdName = "kcl"
rootDesc = `The KCL Command Line Interface (CLI).

KCL is an open-source, constraint-based record and functional language that
enhances the writing of complex configurations, including those for cloud-native
scenarios. The KCL website: https://kcl-lang.io
`
)

// New creates a new cobra client
func New() *cobra.Command {
cmd := &cobra.Command{
Use: "kcl",
Use: cmdName,
Short: "The KCL Command Line Interface (CLI).",
Long: rootDesc,
SilenceUsage: true,
Version: version.GetVersionString(),
}
cmd.AddCommand(NewVersionCmd())
cmd.AddCommand(NewRunCmd())
cmd.SetHelpCommand(&cobra.Command{}) // Disable the help command
cmd.AddCommand(NewModCmd())
cmd.AddCommand(NewRegistryCmd())

bootstrapCmdPlugin(cmd, plugin.NewDefaultPluginHandler([]string{cmdName}))

return cmd
}

func bootstrapCmdPlugin(cmd *cobra.Command, pluginHandler plugin.PluginHandler) {
if pluginHandler == nil {
return
}
if len(os.Args) > 1 {
cmdPathPieces := os.Args[1:]

// only look for suitable extension executables if
// the specified command does not already exist
if foundCmd, _, err := cmd.Find(cmdPathPieces); err != nil {
// Also check the commands that will be added by Cobra.
// These commands are only added once rootCmd.Execute() is called, so we
// need to check them explicitly here.
var cmdName string // first "non-flag" arguments
for _, arg := range cmdPathPieces {
if !strings.HasPrefix(arg, "-") {
cmdName = arg
break
}
}

builtinSubcmdExist := false
for _, subcmd := range foundCmd.Commands() {
if subcmd.Name() == cmdName {
builtinSubcmdExist = true
break
}
}
switch cmdName {
// Don't search for a plugin
case "help", cobra.ShellCompRequestCmd, cobra.ShellCompNoDescRequestCmd:
default:
if !builtinSubcmdExist {
if err := plugin.HandlePluginCommand(pluginHandler, cmdPathPieces, false); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
// Run the run command for the root command. alias kcl="kcl run"
cmd := NewRunCmd()
cmd.SetArgs(cmdPathPieces)
if err := cmd.Execute(); err != nil {
os.Exit(1)
}
os.Exit(0)
}
}
}
}
}
14 changes: 14 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.19
require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/spf13/cobra v1.7.0
github.com/urfave/cli/v2 v2.25.0
kcl-lang.io/kcl-go v0.6.1-0.20231023065115-16ee99bd07f7
kcl-lang.io/kcl-openapi v0.5.1
kcl-lang.io/kpm v0.3.7
Expand Down Expand Up @@ -90,28 +91,41 @@ require (
github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect
github.com/acomagu/bufpipe v1.0.4 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cloudflare/circl v1.1.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/color v1.10.0 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-git/go-billy/v5 v5.4.1 // indirect
github.com/go-git/go-git/v5 v5.6.1 // indirect
github.com/goccy/go-yaml v1.11.0 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/iancoleman/strcase v0.3.0 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
github.com/otiai10/copy v1.9.0 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/qri-io/jsonpointer v0.1.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/skeema/knownhosts v1.1.0 // indirect
github.com/thoas/go-funk v0.9.3 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/tools v0.8.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
oras.land/oras-go v1.2.3 // indirect
oras.land/oras-go/v2 v2.3.0 // indirect
Expand Down
Loading
Loading