diff --git a/cmd/invoke.go b/cmd/invoke.go index f2095cec..eb31287e 100644 --- a/cmd/invoke.go +++ b/cmd/invoke.go @@ -22,7 +22,7 @@ func NewInvokeCmd(newClient ClientFactory) *cobra.Command { Short: "Invoke a Function", Long: ` NAME - {{.Name}} invoke - Invoke a Function. + {{.Name}} invoke - test a Function by invoking it with test data SYNOPSIS {{.Name}} invoke [-t|--target] [-f|--format] diff --git a/cmd/languages.go b/cmd/languages.go new file mode 100644 index 00000000..9f876152 --- /dev/null +++ b/cmd/languages.go @@ -0,0 +1,123 @@ +package cmd + +import ( + "encoding/json" + "fmt" + "os" + + "github.com/ory/viper" + "github.com/spf13/cobra" + + fn "knative.dev/kn-plugin-func" +) + +func NewLanguagesCmd(newClient ClientFactory) *cobra.Command { + cmd := &cobra.Command{ + Use: "languages", + Short: "Languages", + Long: ` +NAME + {{.Name}} languages - list available language runtimes. + +SYNOPSIS + {{.Name}} languages [--json] [-r|--repository] + +DESCRIPTION + List the language runtimes that are currently available. + This includes embedded (included) language runtimes as well as any installed + via the 'repositories add' command. + + Installed repositories are by default located at ~/.func/repositories + ($XDG_CONFIG_HOME/.func/repositories). This can be overridden with + $FUNC_REPOSITORIES_PATH. + + To specify a URI of a single, specific repository for which languages + should be displayed, use the --repository flag. + + To see templates available for a given language, see the 'templates' command. + + +EXAMPLES + + o Show a list of all available language runtimes + $ {{.Name}} languages + + o Return a list of all language runtimes in JSON + $ {{.Name}} languages --json + + o Return language runtimes in a specific repository + $ {{.Name}} languages --repository=https://github.com/boson-project/func-templates +`, + SuggestFor: []string{"language", "runtime", "runtimes", "lnaguages", "languagse", + "panguages", "manguages", "kanguages", "lsnguages", "lznguages"}, + PreRunE: bindEnv("json", "repository"), + } + + cmd.Flags().BoolP("json", "", false, "Set output to JSON format: $FUNC_JSON)") + cmd.Flags().StringP("repository", "r", "", "URI to a specific repository to consider (Env: $FUNC_REPOSITORY)") + + cmd.SetHelpFunc(defaultTemplatedHelp) + + cmd.RunE = func(cmd *cobra.Command, args []string) error { + return runLanguages(cmd, args, newClient) + } + + return cmd +} + +func runLanguages(cmd *cobra.Command, args []string, newClient ClientFactory) (err error) { + cfg, err := newLanguagesConfig(newClient) + if err != nil { + return + } + + client, done := newClient(ClientConfig{Verbose: cfg.Verbose}, + fn.WithRepository(cfg.Repository), // Use exactly this repo OR + fn.WithRepositoriesPath(cfg.RepositoriesPath)) // Path on disk to installed repos + defer done() + + runtimes, err := client.Runtimes() + if err != nil { + return + } + + if cfg.JSON { + var s []byte + s, err = json.MarshalIndent(runtimes, "", " ") + if err != nil { + return + } + fmt.Fprintln(cmd.OutOrStdout(), string(s)) + } else { + for _, runtime := range runtimes { + fmt.Fprintln(cmd.OutOrStdout(), runtime) + } + } + return +} + +type languagesConfig struct { + Verbose bool + Repository string // Consider only a specific repository (URI) + RepositoriesPath string // Override location on disk of "installed" repos + JSON bool // output as JSON +} + +func newLanguagesConfig(newClient ClientFactory) (cfg languagesConfig, err error) { + // Repositories Path + // Not exposed as a flag due to potential confusion with the more likely + // "repository" flag, but still available as an environment variable + repositoriesPath := os.Getenv("FUNC_REPOSITORIES_PATH") + if repositoriesPath == "" { // if no env var provided + repositoriesPath = fn.New().RepositoriesPath() // default to ~/.config/func/repositories + } + + cfg = languagesConfig{ + Verbose: viper.GetBool("verbose"), + Repository: viper.GetString("repository"), + RepositoriesPath: repositoriesPath, + JSON: viper.GetBool("json"), + } + + return +} diff --git a/cmd/languages_test.go b/cmd/languages_test.go new file mode 100644 index 00000000..e98ea211 --- /dev/null +++ b/cmd/languages_test.go @@ -0,0 +1,62 @@ +package cmd + +import ( + "testing" + + fn "knative.dev/kn-plugin-func" + . "knative.dev/kn-plugin-func/testing" +) + +// TestLanguages_Default ensures that the default behavior of listing +// all supported languages is to print a plain text list of all the builtin +// language runtimes. +func TestLanguages_Default(t *testing.T) { + defer WithEnvVar(t, "XDG_CONFIG_HOME", t.TempDir())() // ignore user-added + buf := piped(t) // gather output + cmd := NewLanguagesCmd(NewClientFactory(func() *fn.Client { + return fn.New() + })) + if err := cmd.Execute(); err != nil { + t.Fatal(err) + } + + expected := `go +node +python +quarkus +rust +springboot +typescript` + output := buf() + if output != expected { + t.Fatalf("expected:\n'%v'\ngot:\n'%v'\n", expected, output) + } +} + +// TestLanguages_JSON ensures that listing languages in --json format returns +// builtin languages as a JSON array. +func TestLanguages_JSON(t *testing.T) { + defer WithEnvVar(t, "XDG_CONFIG_HOME", t.TempDir())() // ignore user-added + buf := piped(t) // gather output + cmd := NewLanguagesCmd(NewClientFactory(func() *fn.Client { + return fn.New() + })) + cmd.SetArgs([]string{"--json"}) + if err := cmd.Execute(); err != nil { + t.Fatal(err) + } + + expected := `[ + "go", + "node", + "python", + "quarkus", + "rust", + "springboot", + "typescript" +]` + output := buf() + if output != expected { + t.Fatalf("expected:\n%v\ngot:\n%v\n", expected, output) + } +}