From 22db2af315776ad53c7be214400bf71482cfc880 Mon Sep 17 00:00:00 2001 From: Lance Ball Date: Thu, 25 May 2023 14:42:45 -0400 Subject: [PATCH 1/5] feat: adds a `func environment` command Adds `func environment` to print the current function execution environment as JSON. See: https://github.com/knative/func/discussions/1676 Signed-off-by: Lance Ball --- cmd/environment.go | 129 +++++++++++++++++++++++++++++ cmd/root.go | 1 + docs/reference/func.md | 1 + docs/reference/func_environment.md | 34 ++++++++ 4 files changed, 165 insertions(+) create mode 100644 cmd/environment.go create mode 100644 docs/reference/func_environment.md diff --git a/cmd/environment.go b/cmd/environment.go new file mode 100644 index 0000000000..64c1705c34 --- /dev/null +++ b/cmd/environment.go @@ -0,0 +1,129 @@ +package cmd + +import ( + "encoding/json" + "fmt" + + "github.com/ory/viper" + "github.com/spf13/cobra" + + "knative.dev/func/pkg/config" + "knative.dev/func/pkg/functions" + "knative.dev/func/pkg/k8s" +) + +func NewEnvironmentCmd(newClient ClientFactory, version *Version) *cobra.Command { + cmd := &cobra.Command{ + Use: "environment", + Short: "Display function execution environment information", + Long: ` +NAME + {{rootCmdUse}} environment + +SYNOPSIS + {{rootCmdUse}} environment - display function execution environment information + +DESCRIPTION + Display information about the function execution environment, including + the version of func, the version of the function spec, the default builder, + available runtimes, and available templates. +`, + SuggestFor: []string{"env", "environemtn", "enviroment", "enviornment", "enviroment"}, + RunE: func(cmd *cobra.Command, args []string) error { + return runEnvironment(cmd, newClient, version) + }, + } + cfg, err := config.NewDefault() + if err != nil { + fmt.Fprintf(cmd.OutOrStdout(), "error loading config at '%v'. %v\n", config.File(), err) + } + + addVerboseFlag(cmd, cfg.Verbose) + + return cmd +} + +type Environment struct { + Version string + Build string + SpecVersion string + SocatImage string + TarImage string + Languages []string + Templates map[string][]string + Defaults config.Global +} + +func runEnvironment(cmd *cobra.Command, newClient ClientFactory, v *Version) (err error) { + cfg, err := newEnvironmentConfig() + if err != nil { + return + } + + client := functions.New(functions.WithVerbose(cfg.Verbose)) + r, err := getRuntimes(client) + if err != nil { + return + } + t, err := getTemplates(client, r) + if err != nil { + return + } + + defaults, err := config.NewDefault() + if err != nil { + fmt.Fprintf(cmd.OutOrStdout(), "error loading config at '%v'. %v\n", config.File(), err) + } + + environment := Environment{ + Version: v.String(), + Build: v.Hash, + SpecVersion: functions.LastSpecVersion(), + SocatImage: k8s.SocatImage, + TarImage: k8s.TarImage, + Languages: r, + Templates: t, + Defaults: defaults, + } + + if s, err := json.MarshalIndent(environment, "", " "); err != nil { + return err + } else { + fmt.Fprintln(cmd.OutOrStdout(), string(s)) + } + + return nil +} + +func getRuntimes(client *functions.Client) ([]string, error) { + runtimes, err := client.Runtimes() + if err != nil { + return nil, err + } + return runtimes, nil +} + +func getTemplates(client *functions.Client, runtimes []string) (map[string][]string, error) { + templateMap := make(map[string][]string) + for _, runtime := range runtimes { + templates, err := client.Templates().List(runtime) + if err != nil { + return nil, err + } + templateMap[runtime] = templates + } + return templateMap, nil +} + +type environmentConfig struct { + Verbose bool + // TODO: add format (e.g. JSON/YAML) +} + +func newEnvironmentConfig() (cfg environmentConfig, err error) { + cfg = environmentConfig{ + Verbose: viper.GetBool("verbose"), + } + + return +} diff --git a/cmd/root.go b/cmd/root.go index 04e6e7f32f..a872b0f9a7 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -90,6 +90,7 @@ Learn more about Knative at: https://knative.dev`, cfg.Name), NewLanguagesCmd(newClient), NewTemplatesCmd(newClient), NewRepositoryCmd(newClient), + NewEnvironmentCmd(newClient, &cfg.Version), }, }, { diff --git a/docs/reference/func.md b/docs/reference/func.md index 1df7423b9b..b0267a209e 100644 --- a/docs/reference/func.md +++ b/docs/reference/func.md @@ -30,6 +30,7 @@ Learn more about Knative at: https://knative.dev * [func delete](func_delete.md) - Undeploy a function * [func deploy](func_deploy.md) - Deploy a function * [func describe](func_describe.md) - Describe a function +* [func environment](func_environment.md) - Display function execution environment information * [func invoke](func_invoke.md) - Invoke a local or remote function * [func languages](func_languages.md) - List available function language runtimes * [func list](func_list.md) - List deployed functions diff --git a/docs/reference/func_environment.md b/docs/reference/func_environment.md new file mode 100644 index 0000000000..650a7ef393 --- /dev/null +++ b/docs/reference/func_environment.md @@ -0,0 +1,34 @@ +## func environment + +Display function execution environment information + +### Synopsis + + +NAME + func environment + +SYNOPSIS + func environment - display function execution environment information + +DESCRIPTION + Display information about the function execution environment, including + the version of func, the version of the function spec, the default builder, + available runtimes, and available templates. + + +``` +func environment +``` + +### Options + +``` + -h, --help help for environment + -v, --verbose Print verbose logs ($FUNC_VERBOSE) +``` + +### SEE ALSO + +* [func](func.md) - func manages Knative Functions + From 424d65f80e95ca885f51bae0287778ce1a096d45 Mon Sep 17 00:00:00 2001 From: Lance Ball Date: Thu, 25 May 2023 14:46:56 -0400 Subject: [PATCH 2/5] fixup Signed-off-by: Lance Ball --- cmd/environment.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/environment.go b/cmd/environment.go index 64c1705c34..b38da41498 100644 --- a/cmd/environment.go +++ b/cmd/environment.go @@ -72,7 +72,7 @@ func runEnvironment(cmd *cobra.Command, newClient ClientFactory, v *Version) (er defaults, err := config.NewDefault() if err != nil { - fmt.Fprintf(cmd.OutOrStdout(), "error loading config at '%v'. %v\n", config.File(), err) + return } environment := Environment{ From 779dad1b5bb695846a82bf965aa2e5306c5fc72d Mon Sep 17 00:00:00 2001 From: Lance Ball Date: Fri, 26 May 2023 11:43:08 -0400 Subject: [PATCH 3/5] fixup: add environment variables Signed-off-by: Lance Ball --- cmd/environment.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cmd/environment.go b/cmd/environment.go index b38da41498..0148243c43 100644 --- a/cmd/environment.go +++ b/cmd/environment.go @@ -3,6 +3,8 @@ package cmd import ( "encoding/json" "fmt" + "os" + "strings" "github.com/ory/viper" "github.com/spf13/cobra" @@ -51,6 +53,7 @@ type Environment struct { TarImage string Languages []string Templates map[string][]string + Environment []string Defaults config.Global } @@ -69,7 +72,12 @@ func runEnvironment(cmd *cobra.Command, newClient ClientFactory, v *Version) (er if err != nil { return } - + var envs []string + for _, e := range os.Environ() { + if strings.HasPrefix(e, "FUNC_") { + envs = append(envs, e) + } + } defaults, err := config.NewDefault() if err != nil { return @@ -83,6 +91,7 @@ func runEnvironment(cmd *cobra.Command, newClient ClientFactory, v *Version) (er TarImage: k8s.TarImage, Languages: r, Templates: t, + Environment: envs, Defaults: defaults, } From 8a03b375a3840435698130ac4321de2c7eb67e2c Mon Sep 17 00:00:00 2001 From: Lance Ball Date: Fri, 26 May 2023 12:06:25 -0400 Subject: [PATCH 4/5] fixup: add cluster host Signed-off-by: Lance Ball --- cmd/environment.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cmd/environment.go b/cmd/environment.go index 0148243c43..8e63bad896 100644 --- a/cmd/environment.go +++ b/cmd/environment.go @@ -54,6 +54,7 @@ type Environment struct { Languages []string Templates map[string][]string Environment []string + Cluster string Defaults config.Global } @@ -83,6 +84,14 @@ func runEnvironment(cmd *cobra.Command, newClient ClientFactory, v *Version) (er return } + var host string + cc, err := k8s.GetClientConfig().ClientConfig() + if err != nil { + fmt.Printf("Error getting client config %v\n", err) + } else { + host = cc.Host + } + environment := Environment{ Version: v.String(), Build: v.Hash, @@ -92,6 +101,7 @@ func runEnvironment(cmd *cobra.Command, newClient ClientFactory, v *Version) (er Languages: r, Templates: t, Environment: envs, + Cluster: host, Defaults: defaults, } From 7aab1b8448e905635d26d7ebc901e11a96b3aa95 Mon Sep 17 00:00:00 2001 From: Lance Ball Date: Tue, 30 May 2023 17:21:13 -0400 Subject: [PATCH 5/5] fixup: review feedback Signed-off-by: Lance Ball --- cmd/environment.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/cmd/environment.go b/cmd/environment.go index 8e63bad896..a92d493ec9 100644 --- a/cmd/environment.go +++ b/cmd/environment.go @@ -47,7 +47,8 @@ DESCRIPTION type Environment struct { Version string - Build string + GitRevision string + BuildDate string SpecVersion string SocatImage string TarImage string @@ -64,7 +65,9 @@ func runEnvironment(cmd *cobra.Command, newClient ClientFactory, v *Version) (er return } + // Create a client to get runtimes and templates client := functions.New(functions.WithVerbose(cfg.Verbose)) + r, err := getRuntimes(client) if err != nil { return @@ -73,28 +76,40 @@ func runEnvironment(cmd *cobra.Command, newClient ClientFactory, v *Version) (er if err != nil { return } + + // Get all environment variables that start with FUNC_ var envs []string for _, e := range os.Environ() { if strings.HasPrefix(e, "FUNC_") { envs = append(envs, e) } } + + // If no environment variables are set, make sure we return an empty array + // otherwise the output is "null" instead of "[]" + if len(envs) == 0 { + envs = make([]string, 0) + } + + // Get global defaults defaults, err := config.NewDefault() if err != nil { return } + // Gets the cluster host var host string cc, err := k8s.GetClientConfig().ClientConfig() if err != nil { - fmt.Printf("Error getting client config %v\n", err) + fmt.Printf("error getting client config %v\n", err) } else { host = cc.Host } environment := Environment{ Version: v.String(), - Build: v.Hash, + GitRevision: v.Hash, + BuildDate: v.Date, SpecVersion: functions.LastSpecVersion(), SocatImage: k8s.SocatImage, TarImage: k8s.TarImage,