mirror of https://github.com/knative/func.git
154 lines
5.8 KiB
Go
154 lines
5.8 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"path/filepath"
|
|
|
|
"github.com/ory/viper"
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/boson-project/faas"
|
|
"github.com/boson-project/faas/buildpacks"
|
|
"github.com/boson-project/faas/docker"
|
|
"github.com/boson-project/faas/knative"
|
|
"github.com/boson-project/faas/progress"
|
|
"github.com/boson-project/faas/prompt"
|
|
)
|
|
|
|
func init() {
|
|
root.AddCommand(createCmd)
|
|
createCmd.Flags().BoolP("confirm", "c", false, "Prompt to confirm all configuration options - $FAAS_CONFIRM")
|
|
createCmd.Flags().StringP("image", "i", "", "Optional full image name, in form [registry]/[namespace]/[name]:[tag] for example quay.io/myrepo/project.name:latest (overrides --registry) - $FAAS_IMAGE")
|
|
createCmd.Flags().StringP("namespace", "n", "", "Override namespace into which the Function is deployed (on supported platforms). Default is to use currently active underlying platform setting - $FAAS_NAMESPACE")
|
|
createCmd.Flags().StringP("registry", "r", "", "Registry for built images, ex 'docker.io/myuser' or just 'myuser'. Optional if --image provided. - $FAAS_REGISTRY")
|
|
createCmd.Flags().StringP("runtime", "l", faas.DefaultRuntime, "Function runtime language/framework. Default runtime is 'go'. Available runtimes: 'node', 'quarkus' and 'go'. - $FAAS_RUNTIME")
|
|
createCmd.Flags().StringP("templates", "", filepath.Join(configPath(), "templates"), "Extensible templates path. - $FAAS_TEMPLATES")
|
|
createCmd.Flags().StringP("trigger", "t", faas.DefaultTrigger, "Function trigger. Default trigger is 'http'. Available triggers: 'http' and 'events' - $FAAS_TRIGGER")
|
|
|
|
var err error
|
|
err = createCmd.RegisterFlagCompletionFunc("image", CompleteRegistryList)
|
|
if err != nil {
|
|
fmt.Println("Error while calling RegisterFlagCompletionFunc: ", err)
|
|
}
|
|
err = createCmd.RegisterFlagCompletionFunc("runtime", CompleteRuntimeList)
|
|
if err != nil {
|
|
fmt.Println("Error while calling RegisterFlagCompletionFunc: ", err)
|
|
}
|
|
}
|
|
|
|
var createCmd = &cobra.Command{
|
|
Use: "create <path>",
|
|
Short: "Create a new Function, including initialization of local files and deployment",
|
|
Long: `Create a new Function, including initialization of local files and deployment
|
|
|
|
Creates a new Function project at <path>. If <path> does not exist, it is
|
|
created. The Function name is the name of the leaf directory at <path>. After
|
|
creating the project, a container image is created and is deployed. This
|
|
command wraps "init", "build" and "deploy" all up into one command.
|
|
|
|
The runtime, trigger, image name, image registry, and namespace may all be
|
|
specified as flags on the command line, and will subsequently be the default
|
|
values when an image is built or a Function is deployed. If the image name and
|
|
image registry are both unspecified, the user will be prompted for an image
|
|
registry, and the image name can be inferred from that plus the function
|
|
name. The function name, namespace and image name are all persisted in the
|
|
project configuration file faas.yaml.
|
|
`,
|
|
SuggestFor: []string{"cerate", "new"},
|
|
PreRunE: bindEnv("image", "namespace", "registry", "runtime", "templates", "trigger", "confirm"),
|
|
RunE: runCreate,
|
|
}
|
|
|
|
func runCreate(cmd *cobra.Command, args []string) (err error) {
|
|
config := newCreateConfig(args).Prompt()
|
|
|
|
function := faas.Function{
|
|
Name: config.initConfig.Name,
|
|
Root: config.initConfig.Path,
|
|
Runtime: config.initConfig.Runtime,
|
|
Trigger: config.Trigger,
|
|
Image: config.Image,
|
|
}
|
|
|
|
if function.Image == "" && config.Registry == "" {
|
|
fmt.Print("A registry for Function images is required. For example, 'docker.io/tigerteam'.\n\n")
|
|
config.Registry = prompt.ForString("Registry for Function images", "")
|
|
if config.Registry == "" {
|
|
return fmt.Errorf("Unable to determine Function image name")
|
|
}
|
|
}
|
|
|
|
// Defined in root command
|
|
verbose := viper.GetBool("verbose")
|
|
|
|
builder := buildpacks.NewBuilder()
|
|
builder.Verbose = verbose
|
|
|
|
pusher := docker.NewPusher()
|
|
pusher.Verbose = verbose
|
|
|
|
deployer, err := knative.NewDeployer(config.Namespace)
|
|
if err != nil {
|
|
return
|
|
}
|
|
deployer.Verbose = verbose
|
|
|
|
listener := progress.New()
|
|
listener.Verbose = verbose
|
|
|
|
client := faas.New(
|
|
faas.WithVerbose(verbose),
|
|
faas.WithTemplates(config.Templates),
|
|
faas.WithRegistry(config.Registry), // for deriving image name when --image not provided explicitly.
|
|
faas.WithBuilder(builder),
|
|
faas.WithPusher(pusher),
|
|
faas.WithDeployer(deployer),
|
|
faas.WithProgressListener(listener))
|
|
|
|
return client.Create(function)
|
|
}
|
|
|
|
type createConfig struct {
|
|
initConfig
|
|
deployConfig
|
|
// Note that ambiguous references set to assume .initConfig
|
|
}
|
|
|
|
func newCreateConfig(args []string) createConfig {
|
|
return createConfig{
|
|
initConfig: newInitConfig(args),
|
|
deployConfig: newDeployConfig(),
|
|
}
|
|
}
|
|
|
|
// Prompt the user with value of config members, allowing for interactive changes.
|
|
// Skipped if not in an interactive terminal (non-TTY), or if --confirm (agree to
|
|
// all prompts) was not explicitly set.
|
|
func (c createConfig) Prompt() createConfig {
|
|
if !interactiveTerminal() || !c.initConfig.Confirm {
|
|
// Just print the basics if not confirming
|
|
fmt.Printf("Project path: %v\n", c.initConfig.Path)
|
|
fmt.Printf("Function name: %v\n", c.initConfig.Name)
|
|
fmt.Printf("Runtime: %v\n", c.Runtime)
|
|
fmt.Printf("Trigger: %v\n", c.Trigger)
|
|
return c
|
|
}
|
|
|
|
derivedName, derivedPath := deriveNameAndAbsolutePathFromPath(prompt.ForString("Project path", c.initConfig.Path, prompt.WithRequired(true)))
|
|
return createConfig{
|
|
initConfig: initConfig{
|
|
Name: derivedName,
|
|
Path: derivedPath,
|
|
Runtime: prompt.ForString("Runtime", c.Runtime),
|
|
Trigger: prompt.ForString("Trigger", c.Trigger),
|
|
// Templates intentionally omitted from prompt for being an edge case.
|
|
},
|
|
deployConfig: deployConfig{
|
|
buildConfig: buildConfig{
|
|
Registry: prompt.ForString("Registry for Function images", c.buildConfig.Registry),
|
|
},
|
|
Namespace: prompt.ForString("Override default deploy namespace", c.Namespace),
|
|
},
|
|
}
|
|
}
|