mirror of https://github.com/knative/func.git
181 lines
4.6 KiB
Go
181 lines
4.6 KiB
Go
package cmd
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"text/tabwriter"
|
|
|
|
"github.com/ory/viper"
|
|
"github.com/spf13/cobra"
|
|
|
|
"knative.dev/func/pkg/config"
|
|
fn "knative.dev/func/pkg/functions"
|
|
)
|
|
|
|
// ErrTemplateRepoDoesNotExist is a sentinel error if a template repository responds with 404 status code
|
|
var ErrTemplateRepoDoesNotExist = errors.New("template repo does not exist")
|
|
|
|
func NewTemplatesCmd(newClient ClientFactory) *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "templates",
|
|
Short: "List available function source templates",
|
|
Long: `
|
|
NAME
|
|
{{rootCmdUse}} templates - list available function source templates
|
|
|
|
SYNOPSIS
|
|
{{rootCmdUse}} templates [language] [--json] [-r|--repository]
|
|
|
|
DESCRIPTION
|
|
List all templates available, optionally for a specific language runtime.
|
|
|
|
To specify a URI of a single, specific repository for which templates
|
|
should be displayed, use the --repository flag.
|
|
|
|
Installed repositories are by default located at ~/.func/repositories
|
|
($XDG_CONFIG_HOME/.func/repositories). This can be overridden with
|
|
$FUNC_REPOSITORIES_PATH.
|
|
|
|
To see all available language runtimes, see the 'languages' command.
|
|
|
|
|
|
EXAMPLES
|
|
|
|
o Show a list of all available templates grouped by language runtime
|
|
$ {{rootCmdUse}} templates
|
|
|
|
o Show a list of all templates for the Go runtime
|
|
$ {{rootCmdUse}} templates go
|
|
|
|
o Return a list of all template runtimes in JSON output format
|
|
$ {{rootCmdUse}} templates --json
|
|
|
|
o Return Go templates in a specific repository
|
|
$ {{rootCmdUse}} templates go --repository=https://github.com/boson-project/templates
|
|
`,
|
|
PreRunE: bindEnv("json", "repository", "verbose"),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return runTemplates(cmd, args, newClient)
|
|
},
|
|
}
|
|
|
|
cfg, err := config.NewDefault()
|
|
if err != nil {
|
|
fmt.Fprintf(cmd.OutOrStdout(), "error loading config at '%v'. %v\n", config.File(), err)
|
|
}
|
|
|
|
cmd.Flags().Bool("json", false, "Set output to JSON format. (Env: $FUNC_JSON)")
|
|
cmd.Flags().StringP("repository", "r", "", "URI to a specific repository to consider ($FUNC_REPOSITORY)")
|
|
addVerboseFlag(cmd, cfg.Verbose)
|
|
|
|
return cmd
|
|
}
|
|
|
|
func runTemplates(cmd *cobra.Command, args []string, newClient ClientFactory) (err error) {
|
|
// Gather config
|
|
cfg, err := newTemplatesConfig()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// Simple ping to the repo to avoid subsequent errors from http package if it does not exist
|
|
if cfg.Repository != "" {
|
|
res, err := http.Get(cfg.Repository)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer res.Body.Close()
|
|
if res.StatusCode == http.StatusNotFound {
|
|
return ErrTemplateRepoDoesNotExist
|
|
}
|
|
}
|
|
|
|
// Client which will provide data
|
|
client, done := newClient(
|
|
ClientConfig{Verbose: cfg.Verbose},
|
|
fn.WithRepository(cfg.Repository))
|
|
defer done()
|
|
|
|
// For a single language runtime
|
|
// -------------------
|
|
if len(args) == 1 {
|
|
templates, err := client.Templates().List(args[0])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if cfg.JSON {
|
|
s, err := json.MarshalIndent(templates, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Fprintln(cmd.OutOrStdout(), string(s))
|
|
} else {
|
|
for _, template := range templates {
|
|
fmt.Fprintln(cmd.OutOrStdout(), template)
|
|
}
|
|
}
|
|
return nil
|
|
} else if len(args) > 1 {
|
|
return errors.New("unexpected extra arguments")
|
|
}
|
|
|
|
// All language runtimes
|
|
// ------------
|
|
runtimes, err := client.Runtimes()
|
|
if err != nil {
|
|
return
|
|
}
|
|
if cfg.JSON {
|
|
// Gather into a single data structure for printing as json
|
|
templateMap := make(map[string][]string)
|
|
for _, runtime := range runtimes {
|
|
templates, err := client.Templates().List(runtime)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
templateMap[runtime] = templates
|
|
}
|
|
s, err := json.MarshalIndent(templateMap, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Fprintln(cmd.OutOrStdout(), string(s))
|
|
} else {
|
|
// print using a formatted writer (sorted)
|
|
builder := strings.Builder{}
|
|
writer := tabwriter.NewWriter(&builder, 0, 0, 3, ' ', 0)
|
|
fmt.Fprint(writer, "LANGUAGE\tTEMPLATE\n")
|
|
for _, runtime := range runtimes {
|
|
templates, err := client.Templates().List(runtime)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, template := range templates {
|
|
fmt.Fprintf(writer, "%v\t%v\n", runtime, template)
|
|
}
|
|
}
|
|
writer.Flush()
|
|
fmt.Fprint(cmd.OutOrStdout(), builder.String())
|
|
}
|
|
return
|
|
}
|
|
|
|
type templatesConfig struct {
|
|
Verbose bool
|
|
Repository string // Consider only a specific repository (URI)
|
|
JSON bool // output as JSON
|
|
}
|
|
|
|
func newTemplatesConfig() (cfg templatesConfig, err error) {
|
|
cfg = templatesConfig{
|
|
Verbose: viper.GetBool("verbose"),
|
|
Repository: viper.GetString("repository"),
|
|
JSON: viper.GetBool("json"),
|
|
}
|
|
|
|
return
|
|
}
|